library(ggpubr)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Registered S3 methods overwritten by 'car':
  method                          from
  influence.merMod                lme4
  cooks.distance.influence.merMod lme4
  dfbeta.influence.merMod         lme4
  dfbetas.influence.merMod        lme4
response <- try(system('~/google-cloud-sdk/bin/gcloud projects list --quiet', intern = T))
projectid <- strsplit(response[2], " ")[[1]][1]
options(na.action = "na.fail") 
source("./dredge_functions.R")
dredge_and_subset <- function(data) {
  model <- lm(
    response ~ foraging_niche + trophic_niche + is_nocturnal + pc1 + pc2 + pc3 + pc4 + total_species,
    data=data
  )
  dredge_result <- dredge(model)
  summary(model.avg(dredge_result, subset = delta < 10))
}
load_niche_data <- function() {
  filename <- 'species_analysis_cache.csv'
  
  if (!file.exists(filename)) {
    
    sql <- "
        SELECT 
          niche_name,
          foraging_niche, 
          trophic_niche, 
          is_noctural, 
          total_species,
          merlin_10_perc_ratio, 
          merlin_20_perc_ratio,
          merlin_ever_perc_ratio,
          birdlife_10_perc_ratio, 
          birdlife_20_perc_ratio,
          birdlife_ever_perc_ratio,
          either_10_perc_ratio, 
          either_20_perc_ratio, 
          either_ever_perc_ratio,
          both_10_perc_ratio, 
          both_20_perc_ratio,
          both_ever_perc_ratio,
          body_morphspace.pc1.mean AS pc1, 
          body_morphspace.pc2.mean AS pc2, 
          body_morphspace.pc3.mean AS pc3, 
          body_morphspace.pc4.mean AS pc4
        FROM `endless-matter-297214.model2.niche_analysis_model` LIMIT 1000 
    "
  
    tb <- bq_project_query(projectid, sql)

    data <- bq_table_download(tb)
    write_csv(data, filename)
  }
  
  data <- read_csv(filename)
  
  data[is.na(data$foraging_niche),]$foraging_niche <- 'Omnivore'
  
  data$foraging_niche = as.factor(data$foraging_niche)
  data$trophic_niche = as.factor(data$trophic_niche)
  data$is_nocturnal = as.factor(data$is_noctural)
  
  data
}

data_for_response <- function(column_name_for_response) {
  data <- load_niche_data()
  names(data)[names(data) == column_name_for_response] <- "response"
  
  data[,c("niche_name", "response", "foraging_niche", "trophic_niche", "is_nocturnal", "pc1", "pc2", "pc3", "pc4", "total_species")]
}
0.25 Percentile - 10% of species
merlin_10_data <- data_for_response('merlin_10_perc_ratio')

── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  niche_name = col_character(),
  foraging_niche = col_character(),
  trophic_niche = col_character(),
  is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
merlin_10_data
merlin_10_result <- dredge_and_subset(merlin_10_data)
Fixed term is "(Intercept)"
merlin_10_summ <- model_summary('merlin_10', 'species', merlin_10_result)
merlin_10_summ
birdlife_10_data <- data_for_response('birdlife_10_perc_ratio')

── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  niche_name = col_character(),
  foraging_niche = col_character(),
  trophic_niche = col_character(),
  is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
birdlife_10_result <- dredge_and_subset(birdlife_10_data)
Fixed term is "(Intercept)"
birdlife_10_summ <- model_summary('birdlife_10', 'species', birdlife_10_result)
birdlife_10_summ
both_10_data <- data_for_response('both_10_perc_ratio')

── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  niche_name = col_character(),
  foraging_niche = col_character(),
  trophic_niche = col_character(),
  is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
both_10_result <- dredge_and_subset(both_10_data)
Fixed term is "(Intercept)"
both_10_summ <- model_summary('both_10', 'species', both_10_result)
both_10_summ
either_10_data <- data_for_response('either_10_perc_ratio')

── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  niche_name = col_character(),
  foraging_niche = col_character(),
  trophic_niche = col_character(),
  is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
either_10_result <- dredge_and_subset(either_10_data)
Fixed term is "(Intercept)"
either_10_summ <- model_summary('either_10', 'species', either_10_result)
either_10_summ
Full result for 10% of species
all_species_results <- full_join(full_join(merlin_10_summ, birdlife_10_summ), full_join(both_10_summ, either_10_summ))
Joining, by = c("explanatory", "model")
Joining, by = c("explanatory", "model")
Joining, by = c("explanatory", "model")
write_csv(all_species_results, "species_analysis_result_10_perc.csv")
0.75 Percentile - 20% of species
merlin_20_data <- data_for_response('merlin_20_perc_ratio')

── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  niche_name = col_character(),
  foraging_niche = col_character(),
  trophic_niche = col_character(),
  is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
merlin_20_result <- dredge_and_subset(merlin_20_data)
Fixed term is "(Intercept)"
merlin_20_summ <- model_summary('merlin_20', 'species', merlin_20_result)
merlin_20_summ
birdlife_20_data <- data_for_response('birdlife_20_perc_ratio')

── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  niche_name = col_character(),
  foraging_niche = col_character(),
  trophic_niche = col_character(),
  is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
birdlife_20_result <- dredge_and_subset(birdlife_20_data)
Fixed term is "(Intercept)"
birdlife_20_summ <- model_summary('birdlife_20', 'species', birdlife_20_result)
birdlife_20_summ
both_20_data <- data_for_response('both_20_perc_ratio')

── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  niche_name = col_character(),
  foraging_niche = col_character(),
  trophic_niche = col_character(),
  is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
both_20_result <- dredge_and_subset(both_20_data)
Fixed term is "(Intercept)"
both_20_summ <- model_summary('both_20', 'species', both_20_result)
both_20_summ
either_20_data <- data_for_response('either_20_perc_ratio')

── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  niche_name = col_character(),
  foraging_niche = col_character(),
  trophic_niche = col_character(),
  is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
either_20_result <- dredge_and_subset(either_20_data)
Fixed term is "(Intercept)"
either_20_summ <- model_summary('either_20', 'species', either_20_result)
either_20_summ
Full result for 10% of species
all_species_results <- full_join(full_join(merlin_20_summ, birdlife_20_summ), full_join(both_20_summ, either_20_summ))
Joining, by = c("explanatory", "model")
Joining, by = c("explanatory", "model")
Joining, by = c("explanatory", "model")
write_csv(all_species_results, "species_analysis_result_20_perc.csv")
Comparing the 2 percentiles
ggplot(merlin_10_data, aes(x = response)) + geom_bar(width = 0.1)
Warning: position_stack requires non-overlapping x intervals

bind_sets <- function(first_percentile, second_percentile) {
  first_percentile$percentile <- "Top 10%"
  second_percentile$percentile <- "Top 20%"
  rbind(first_percentile, second_percentile)
}

merlin_species_data <- bind_sets(merlin_10_data,  merlin_20_data)
birdlife_species_data <- bind_sets(birdlife_10_data,  birdlife_20_data)
either_species_data <- bind_sets(either_10_data,  either_20_data)
both_species_data <- bind_sets(both_10_data,  both_20_data)
diff_set <- function(first_percentile, second_percentile) {
  second_percentile$response_20 <- second_percentile$response
  
  result <- right_join(first_percentile, second_percentile[,c("niche_name", "response_20")], by = c("niche_name"))
  result$diff <- result$response_20 - result$response
  result$increase <- result$diff / result$response_20
  result$increase[is.na(result$increase)] = 0
  result$response_10 <- result$response
  result[,c("response_10", "response_20", "diff", "increase", "foraging_niche", "trophic_niche", "is_nocturnal", "pc1", "pc2", "pc3", "pc4", "total_species")]
}

merlin_diff_data <- diff_set(merlin_10_data,  merlin_20_data)
birdlife_diff_data <- diff_set(birdlife_10_data,  birdlife_20_data)
either_diff_data <- diff_set(either_10_data,  either_20_data)
both_diff_data <- diff_set(both_10_data,  both_20_data)

merlin_diff_data
ggplot(merlin_species_data, aes(x = response, y = trophic_niche, color = percentile)) + geom_boxplot() + theme_bw()

merlin_trophic_niche_niche_anova <- aov(response~trophic_niche + percentile + Error(niche_name), data=merlin_species_data)
summary(merlin_trophic_niche_niche_anova)

Error: niche_name
               Df Sum Sq Mean Sq F value Pr(>F)  
trophic_niche   9  1.762  0.1958   1.679 0.0943 .
Residuals     258 30.084  0.1166                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Error: Within
            Df Sum Sq Mean Sq F value   Pr(>F)    
percentile   1  1.508  1.5077   59.65 2.29e-13 ***
Residuals  267  6.749  0.0253                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
merlin_trophic_niche_niche_anova_i <- aov(response~trophic_niche * percentile + Error(niche_name), data=merlin_species_data)
summary(merlin_trophic_niche_niche_anova_i)

Error: niche_name
               Df Sum Sq Mean Sq F value Pr(>F)  
trophic_niche   9  1.762  0.1958   1.679 0.0943 .
Residuals     258 30.084  0.1166                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Error: Within
                          Df Sum Sq Mean Sq F value   Pr(>F)    
percentile                 1  1.508  1.5077  69.821 4.05e-15 ***
trophic_niche:percentile   9  1.177  0.1308   6.057 1.03e-07 ***
Residuals                258  5.571  0.0216                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
pairwise.wilcox.test(merlin_diff_data$increase, merlin_diff_data$trophic_niche)
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties

    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  merlin_diff_data$increase and merlin_diff_data$trophic_niche 

                      Aquatic predator Frugivore Granivore Herbivore aquatic Herbivore terrestrial Invertivore Nectarivore Omnivore Scavenger
Frugivore             0.5331           -         -         -                 -                     -           -           -        -        
Granivore             1.0000           1.0000    -         -                 -                     -           -           -        -        
Herbivore aquatic     1.0000           0.1167    1.0000    -                 -                     -           -           -        -        
Herbivore terrestrial 1.0000           1.0000    1.0000    1.0000            -                     -           -           -        -        
Invertivore           0.0076           1.0000    1.0000    0.0051            1.0000                -           -           -        -        
Nectarivore           1.0000           1.0000    1.0000    1.0000            1.0000                1.0000      -           -        -        
Omnivore              0.2684           1.0000    1.0000    0.0679            1.0000                1.0000      1.0000      -        -        
Scavenger             1.0000           1.0000    1.0000    1.0000            1.0000                1.0000      1.0000      1.0000   -        
Vertivore             1.0000           1.0000    1.0000    0.5929            1.0000                1.0000      1.0000      1.0000   1.0000   

P value adjustment method: holm 
library(multcomp)
merlin_increase_tropic_niche_anova <-aov(increase~trophic_niche, data=merlin_diff_data)
summary(merlin_increase_tropic_niche_anova)
               Df Sum Sq Mean Sq F value   Pr(>F)    
trophic_niche   9  3.941  0.4379   3.689 0.000229 ***
Residuals     258 30.629  0.1187                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
merlin_increase_tropic_niche_tukey <- cld(glht(merlin_increase_tropic_niche_anova, linfct=mcp(trophic_niche="Tukey")))
Warning in RET$pfunction("adjusted", ...) :
  Completion with error > abseps
Warning in RET$pfunction("adjusted", ...) :
  Completion with error > abseps
Warning in RET$pfunction("adjusted", ...) :
  Completion with error > abseps
Warning in RET$pfunction("adjusted", ...) :
  Completion with error > abseps
Warning in RET$pfunction("adjusted", ...) :
  Completion with error > abseps
Warning in RET$pfunction("adjusted", ...) :
  Completion with error > abseps
Warning in RET$pfunction("adjusted", ...) :
  Completion with error > abseps
Warning in RET$pfunction("adjusted", ...) :
  Completion with error > abseps
merlin_increase_tropic_niche_tukey
     Aquatic predator             Frugivore             Granivore     Herbivore aquatic Herbivore terrestrial           Invertivore           Nectarivore              Omnivore 
                 "bc"                  "ab"                  "ac"                   "c"                  "ac"                   "a"                  "ac"                  "ab" 
            Scavenger             Vertivore 
                 "ac"                  "ac" 
plot(merlin_increase_tropic_niche_tukey)

with.tukey.label.as.group <- function(tukey, dataset, join_by) {
  labels <- data.frame(tukey$mcletters$Letters)
  labels$category <- rownames(labels)
  colnames(labels) <- c("group", "category")
  
  
  left_join(dataset, labels, by = join_by)
}
merlin_diff_data1 <- with.tukey.label.as.group(merlin_increase_tropic_niche_tukey, merlin_diff_data, c("trophic_niche" = "category"))
merlin_diff_data1
table(merlin_diff_data1$trophic_niche)

     Aquatic predator             Frugivore             Granivore     Herbivore aquatic Herbivore terrestrial           Invertivore           Nectarivore              Omnivore 
                   58                    25                    10                    15                     9                    74                    11                    34 
            Scavenger             Vertivore 
                    3                    29 
ggplot(merlin_diff_data1, aes(x = increase, y = trophic_niche, color = group)) + geom_boxplot() + theme_bw()

ggplot(birdlife_species_data, aes(x = response, y = trophic_niche, color = percentile)) + geom_boxplot() + theme_bw()

birdlife_trophic_niche_niche_anova <- aov(response~trophic_niche + percentile + Error(niche_name), data=birdlife_species_data)
summary(birdlife_trophic_niche_niche_anova)

Error: niche_name
               Df Sum Sq Mean Sq F value Pr(>F)
trophic_niche   9  1.696  0.1885   1.605  0.114
Residuals     258 30.292  0.1174               

Error: Within
            Df Sum Sq Mean Sq F value   Pr(>F)    
percentile   1  1.327  1.3274   60.18 1.84e-13 ***
Residuals  267  5.890  0.0221                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
birdlife_trophic_niche_niche_anova_i <- aov(response~trophic_niche * percentile + Error(niche_name), data=birdlife_species_data)
summary(birdlife_trophic_niche_niche_anova_i)

Error: niche_name
               Df Sum Sq Mean Sq F value Pr(>F)
trophic_niche   9  1.696  0.1885   1.605  0.114
Residuals     258 30.292  0.1174               

Error: Within
                          Df Sum Sq Mean Sq F value   Pr(>F)    
percentile                 1  1.327  1.3274  64.018 4.19e-14 ***
trophic_niche:percentile   9  0.540  0.0600   2.893  0.00282 ** 
Residuals                258  5.350  0.0207                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
birdlife_increase_tropic_niche_anova <-aov(increase~trophic_niche, data=birdlife_diff_data)
summary(birdlife_increase_tropic_niche_anova)
               Df Sum Sq Mean Sq F value Pr(>F)  
trophic_niche   9   2.21  0.2453   1.791 0.0703 .
Residuals     258  35.35  0.1370                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
birdlife_increase_tropic_niche_tukey <- cld(glht(birdlife_increase_tropic_niche_anova, linfct=mcp(trophic_niche="Tukey")))
Warning in RET$pfunction("adjusted", ...) :
  Completion with error > abseps
Warning in RET$pfunction("adjusted", ...) :
  Completion with error > abseps
birdlife_increase_tropic_niche_tukey
     Aquatic predator             Frugivore             Granivore     Herbivore aquatic Herbivore terrestrial           Invertivore           Nectarivore              Omnivore 
                  "b"                  "ab"                  "ab"                  "ab"                  "ab"                   "a"                  "ab"                  "ab" 
            Scavenger             Vertivore 
                 "ab"                  "ab" 
birdlife_diff_data1 <- with.tukey.label.as.group(birdlife_increase_tropic_niche_tukey, birdlife_diff_data, c("trophic_niche" = "category"))
ggplot(birdlife_diff_data1, aes(x = increase, y = trophic_niche, color = group)) + geom_boxplot() + theme_bw()

ggplot(either_species_data, aes(x = response, y = trophic_niche, color = percentile)) + geom_boxplot() + theme_bw()

ggplot(both_species_data, aes(x = response, y = trophic_niche, color = percentile)) + geom_boxplot() + theme_bw()

nrow(merlin_10_data[merlin_10_data$response > 0,])
[1] 96
nrow(merlin_20_data[merlin_20_data$response > 0,])
[1] 128
nrow(birdlife_10_data[birdlife_10_data$response > 0,])
[1] 87
nrow(birdlife_20_data[birdlife_20_data$response > 0,])
[1] 124
nrow(either_10_data[either_10_data$response > 0,])
[1] 94
nrow(either_20_data[either_20_data$response > 0,])
[1] 123
nrow(both_10_data[both_10_data$response > 0,])
[1] 91
nrow(both_20_data[both_20_data$response > 0,])
[1] 128
ggplot(merlin_species_data, aes(x = response, y = foraging_niche, color = percentile)) + geom_boxplot() + theme_bw()

interaction.plot(merlin_species_data$foraging_niche, merlin_species_data$percentile, merlin_species_data$response)

merlin_foraging_niche_anova <- aov(response~foraging_niche + percentile + Error(niche_name), data=merlin_species_data)
summary(merlin_foraging_niche_anova)

Error: niche_name
                Df Sum Sq Mean Sq F value Pr(>F)
foraging_niche  32  4.894  0.1529   1.333  0.118
Residuals      235 26.952  0.1147               

Error: Within
            Df Sum Sq Mean Sq F value   Pr(>F)    
percentile   1  1.508  1.5077   59.65 2.29e-13 ***
Residuals  267  6.749  0.0253                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
merlin_foraging_niche_anova_i <- aov(response~foraging_niche * percentile + Error(niche_name), data=merlin_species_data)
summary(merlin_foraging_niche_anova_i)

Error: niche_name
                Df Sum Sq Mean Sq F value Pr(>F)
foraging_niche  32  4.894  0.1529   1.333  0.118
Residuals      235 26.952  0.1147               

Error: Within
                           Df Sum Sq Mean Sq F value   Pr(>F)    
percentile                  1  1.508  1.5077  68.706 8.81e-15 ***
foraging_niche:percentile  32  1.591  0.0497   2.266 0.000275 ***
Residuals                 235  5.157  0.0219                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
ggplot(birdlife_species_data, aes(x = response, y = foraging_niche, color = percentile)) + geom_boxplot() + theme_bw()

birdlife_foraging_niche_anova <- aov(response~foraging_niche + percentile + Error(niche_name), data=birdlife_species_data)
summary(birdlife_foraging_niche_anova)

Error: niche_name
                Df Sum Sq Mean Sq F value Pr(>F)  
foraging_niche  32  5.519  0.1725   1.531 0.0401 *
Residuals      235 26.470  0.1126                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Error: Within
            Df Sum Sq Mean Sq F value   Pr(>F)    
percentile   1  1.327  1.3274   60.18 1.84e-13 ***
Residuals  267  5.890  0.0221                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
birdlife_foraging_niche_anova_i <- aov(response~foraging_niche * percentile + Error(niche_name), data=birdlife_species_data)
summary(birdlife_foraging_niche_anova_i)

Error: niche_name
                Df Sum Sq Mean Sq F value Pr(>F)  
foraging_niche  32  5.519  0.1725   1.531 0.0401 *
Residuals      235 26.470  0.1126                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Error: Within
                           Df Sum Sq Mean Sq F value   Pr(>F)    
percentile                  1  1.327  1.3274  67.870 1.22e-14 ***
foraging_niche:percentile  32  1.293  0.0404   2.066  0.00118 ** 
Residuals                 235  4.596  0.0196                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
pc_axis_figure <- function(dataset) {
  annotate_figure(
ggarrange(
  ggplot(dataset, aes(x = pc1, y = log(response), color = percentile)) + geom_point(alpha = 0.5) + geom_smooth(method = "lm", se = FALSE) + theme_bw() + rremove("ylab"),
  ggplot(dataset, aes(x = pc2, y = log(response), color = percentile)) + geom_point(alpha = 0.5) + geom_smooth(method = "lm", se = FALSE) + theme_bw() + rremove("ylab"),
  ggplot(dataset, aes(x = pc3, y = log(response), color = percentile)) + geom_point(alpha = 0.5) + geom_smooth(method = "lm", se = FALSE) + theme_bw() + rremove("ylab"),
  ggplot(dataset, aes(x = pc4, y = log(response), color = percentile)) + geom_point(alpha = 0.5) + geom_smooth(method = "lm", se = FALSE) + theme_bw() + rremove("ylab"),
  nrow = 2, ncol = 2, common.legend = T, label.x = 0),
left = text_grob("log(response)", rot = 90))
}
pc_axis_figure(merlin_species_data)
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 312 rows containing non-finite values (stat_smooth).
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 312 rows containing non-finite values (stat_smooth).
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 312 rows containing non-finite values (stat_smooth).
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 312 rows containing non-finite values (stat_smooth).
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 312 rows containing non-finite values (stat_smooth).

library(lme4)
merlin_pc1_model = lmer(response ~ pc1 * percentile + (1|niche_name), data=merlin_species_data)
anova(merlin_pc1_model)
Analysis of Variance Table
               npar  Sum Sq Mean Sq F value
pc1               1 0.00042 0.00042  0.0169
percentile        1 1.50774 1.50774 59.9817
pc1:percentile    1 0.06215 0.06215  2.4724
summary(merlin_pc1_model)
Linear mixed model fit by REML ['lmerMod']
Formula: response ~ pc1 * percentile + (1 | niche_name)
   Data: merlin_species_data

REML criterion at convergence: -8.6

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.4461 -0.5197  0.0155  0.1840  3.3433 

Random effects:
 Groups     Name        Variance Std.Dev.
 niche_name (Intercept) 0.04729  0.2175  
 Residual               0.02514  0.1585  
Number of obs: 536, groups:  niche_name, 268

Fixed effects:
                       Estimate Std. Error t value
(Intercept)            0.117739   0.022322   5.275
pc1                   -0.005011   0.006481  -0.773
percentileTop 20%      0.086293   0.018597   4.640
pc1:percentileTop 20%  0.008490   0.005399   1.572

Correlation of Fixed Effects:
            (Intr) pc1    prT20%
pc1         -0.676              
prcntlTp20% -0.417  0.282       
pc1:prcT20%  0.282 -0.417 -0.676
merlin_pc2_model = lmer(response ~ pc2 * percentile + (1|niche_name), data=merlin_species_data)
anova(merlin_pc2_model)
Analysis of Variance Table
               npar  Sum Sq Mean Sq F value
pc2               1 0.01486 0.01486  0.5864
percentile        1 1.50774 1.50774 59.5009
pc2:percentile    1 0.00812 0.00812  0.3203
summary(merlin_pc2_model)
Linear mixed model fit by REML ['lmerMod']
Formula: response ~ pc2 * percentile + (1 | niche_name)
   Data: merlin_species_data

REML criterion at convergence: -11.2

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.3691 -0.5150  0.0879  0.1354  3.3292 

Random effects:
 Groups     Name        Variance Std.Dev.
 niche_name (Intercept) 0.04706  0.2169  
 Residual               0.02534  0.1592  
Number of obs: 536, groups:  niche_name, 268

Fixed effects:
                       Estimate Std. Error t value
(Intercept)            0.104389   0.016836   6.200
pc2                   -0.008532   0.018597  -0.459
percentileTop 20%      0.104347   0.014086   7.408
pc2:percentileTop 20% -0.008805   0.015559  -0.566

Correlation of Fixed Effects:
            (Intr) pc2    prT20%
pc2          0.217              
prcntlTp20% -0.418 -0.091       
pc2:prcT20% -0.091 -0.418  0.217
merlin_pc3_model = lmer(response ~ pc3 * percentile + (1|niche_name), data=merlin_species_data)
anova(merlin_pc3_model)
Analysis of Variance Table
               npar  Sum Sq Mean Sq F value
pc3               1 0.00044 0.00044  0.0187
percentile        1 1.50774 1.50774 63.7963
pc3:percentile    1 0.46195 0.46195 19.5464
summary(merlin_pc3_model)
Linear mixed model fit by REML ['lmerMod']
Formula: response ~ pc3 * percentile + (1 | niche_name)
   Data: merlin_species_data

REML criterion at convergence: -30.5

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.8609 -0.4057 -0.0338  0.2719  3.7473 

Random effects:
 Groups     Name        Variance Std.Dev.
 niche_name (Intercept) 0.04804  0.2192  
 Residual               0.02363  0.1537  
Number of obs: 536, groups:  niche_name, 268

Fixed effects:
                      Estimate Std. Error t value
(Intercept)            0.10758    0.01638   6.568
pc3                   -0.04333    0.02594  -1.670
percentileTop 20%      0.10282    0.01330   7.730
pc3:percentileTop 20%  0.09314    0.02107   4.421

Correlation of Fixed Effects:
            (Intr) pc3    prT20%
pc3         -0.055              
prcntlTp20% -0.406  0.022       
pc3:prcT20%  0.022 -0.406 -0.055
merlin_pc4_model = lmer(response ~ pc4 * percentile + (1|niche_name), data=merlin_species_data)
anova(merlin_pc4_model)
Analysis of Variance Table
               npar  Sum Sq Mean Sq F value
pc4               1 0.06576 0.06576  2.6061
percentile        1 1.50774 1.50774 59.7558
pc4:percentile    1 0.03687 0.03687  1.4612
summary(merlin_pc4_model)
Linear mixed model fit by REML ['lmerMod']
Formula: response ~ pc4 * percentile + (1 | niche_name)
   Data: merlin_species_data

REML criterion at convergence: -17

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.4101 -0.5034  0.0731  0.1400  3.4938 

Random effects:
 Groups     Name        Variance Std.Dev.
 niche_name (Intercept) 0.04666  0.2160  
 Residual               0.02523  0.1588  
Number of obs: 536, groups:  niche_name, 268

Fixed effects:
                      Estimate Std. Error t value
(Intercept)            0.10678    0.01640   6.513
pc4                    0.03400    0.03543   0.960
percentileTop 20%      0.10683    0.01374   7.777
pc4:percentileTop 20%  0.03588    0.02969   1.209

Correlation of Fixed Effects:
            (Intr) pc4    prT20%
pc4          0.046              
prcntlTp20% -0.419 -0.019       
pc4:prcT20% -0.019 -0.419  0.046
pc_axis_figure(birdlife_species_data)
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 325 rows containing non-finite values (stat_smooth).
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 325 rows containing non-finite values (stat_smooth).
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 325 rows containing non-finite values (stat_smooth).
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 325 rows containing non-finite values (stat_smooth).
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 325 rows containing non-finite values (stat_smooth).

ggplot(merlin_species_data, aes(x = response, y = is_nocturnal, color = percentile)) + geom_boxplot() + theme_bw()

merlin_nocturnal_anova <- aov(response~is_nocturnal + percentile + Error(niche_name), data=merlin_species_data)
summary(merlin_nocturnal_anova)

Error: niche_name
              Df Sum Sq Mean Sq F value Pr(>F)  
is_nocturnal   1  0.462  0.4615   3.912  0.049 *
Residuals    266 31.384  0.1180                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Error: Within
            Df Sum Sq Mean Sq F value   Pr(>F)    
percentile   1  1.508  1.5077   59.65 2.29e-13 ***
Residuals  267  6.749  0.0253                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
merlin_nocturnal_anova_i <- aov(response~is_nocturnal * percentile + Error(niche_name), data=merlin_species_data)
summary(merlin_nocturnal_anova_i)

Error: niche_name
              Df Sum Sq Mean Sq F value Pr(>F)  
is_nocturnal   1  0.462  0.4615   3.912  0.049 *
Residuals    266 31.384  0.1180                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Error: Within
                         Df Sum Sq Mean Sq F value   Pr(>F)    
percentile                1  1.508  1.5077  60.685 1.51e-13 ***
is_nocturnal:percentile   1  0.140  0.1396   5.618   0.0185 *  
Residuals               266  6.609  0.0248                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
ggplot(birdlife_species_data, aes(x = response, y = is_nocturnal, color = percentile)) + geom_boxplot() + theme_bw()

birdlife_nocturnal_anova <- aov(response~is_nocturnal + percentile + Error(niche_name), data=birdlife_species_data)
summary(birdlife_nocturnal_anova)

Error: niche_name
              Df Sum Sq Mean Sq F value Pr(>F)
is_nocturnal   1   0.20  0.1982   1.658  0.199
Residuals    266  31.79  0.1195               

Error: Within
            Df Sum Sq Mean Sq F value   Pr(>F)    
percentile   1  1.327  1.3274   60.18 1.84e-13 ***
Residuals  267  5.890  0.0221                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
birdlife_nocturnal_anova_i <- aov(response~is_nocturnal * percentile + Error(niche_name), data=birdlife_species_data)
summary(birdlife_nocturnal_anova_i)

Error: niche_name
              Df Sum Sq Mean Sq F value Pr(>F)
is_nocturnal   1   0.20  0.1982   1.658  0.199
Residuals    266  31.79  0.1195               

Error: Within
                         Df Sum Sq Mean Sq F value   Pr(>F)    
percentile                1  1.327  1.3274  60.370 1.72e-13 ***
is_nocturnal:percentile   1  0.041  0.0407   1.852    0.175    
Residuals               266  5.849  0.0220                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Investigation of percentiles and presence
ggplot(merlin_species_data, aes(x = total_species, y = log(response), color = percentile)) + geom_point(alpha = 0.5) + geom_smooth(method = "lm", se = FALSE) + theme_bw()
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 312 rows containing non-finite values (stat_smooth).

merlin_species_count_model = lmer(response ~ total_species * percentile + (1|niche_name), data=merlin_species_data)
anova(merlin_species_count_model)
Analysis of Variance Table
                         npar  Sum Sq Mean Sq F value
total_species               1 0.00052 0.00052  0.0206
percentile                  1 1.50774 1.50774 59.4316
total_species:percentile    1 0.00026 0.00026  0.0103
summary(merlin_species_count_model)
Linear mixed model fit by REML ['lmerMod']
Formula: response ~ total_species * percentile + (1 | niche_name)
   Data: merlin_species_data

REML criterion at convergence: 8.6

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.3523 -0.5462  0.1109  0.1216  3.2582 

Random effects:
 Groups     Name        Variance Std.Dev.
 niche_name (Intercept) 0.04717  0.2172  
 Residual               0.02537  0.1593  
Number of obs: 536, groups:  niche_name, 268

Fixed effects:
                                  Estimate Std. Error t value
(Intercept)                      1.064e-01  1.690e-02   6.295
total_species                   -1.420e-05  1.612e-04  -0.088
percentileTop 20%                1.064e-01  1.414e-02   7.527
total_species:percentileTop 20% -1.367e-05  1.348e-04  -0.101

Correlation of Fixed Effects:
            (Intr) ttl_sp prT20%
total_specs -0.229              
prcntlTp20% -0.418  0.096       
ttl_sp:T20%  0.096 -0.418 -0.229
birdlife_species_count_model = lmer(response ~ total_species * percentile + (1|niche_name), data=birdlife_species_data)
anova(birdlife_species_count_model)
Analysis of Variance Table
                         npar Sum Sq Mean Sq F value
total_species               1 0.0000  0.0000  0.0001
percentile                  1 1.3274  1.3274 59.9531
total_species:percentile    1 0.0000  0.0000  0.0001
summary(birdlife_species_count_model)
Linear mixed model fit by REML ['lmerMod']
Formula: response ~ total_species * percentile + (1 | niche_name)
   Data: birdlife_species_data

REML criterion at convergence: -26.3

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.5919 -0.5189  0.0633  0.1497  3.4600 

Random effects:
 Groups     Name        Variance Std.Dev.
 niche_name (Intercept) 0.04906  0.2215  
 Residual               0.02214  0.1488  
Number of obs: 536, groups:  niche_name, 268

Fixed effects:
                                 Estimate Std. Error t value
(Intercept)                     9.946e-02  1.675e-02   5.939
total_species                   9.392e-07  1.597e-04   0.006
percentileTop 20%               9.949e-02  1.321e-02   7.534
total_species:percentileTop 20% 1.518e-06  1.260e-04   0.012

Correlation of Fixed Effects:
            (Intr) ttl_sp prT20%
total_specs -0.229              
prcntlTp20% -0.394  0.090       
ttl_sp:T20%  0.090 -0.394 -0.229
merlin_species_data$present <- merlin_species_data$response > 0

merlin_present_model = lmer(present ~ log(total_species) * percentile + (1|niche_name), data=merlin_species_data)
anova(merlin_present_model)
Analysis of Variance Table
                              npar Sum Sq Mean Sq  F value
log(total_species)               1 7.6804  7.6804 145.5124
percentile                       1 1.9104  1.9104  36.1952
log(total_species):percentile    1 0.0496  0.0496   0.9393
summary(merlin_present_model)
Linear mixed model fit by REML ['lmerMod']
Formula: present ~ log(total_species) * percentile + (1 | niche_name)
   Data: merlin_species_data

REML criterion at convergence: 410.7

Scaled residuals: 
     Min       1Q   Median       3Q      Max 
-2.25242 -0.44048  0.02734  0.24296  2.14911 

Random effects:
 Groups     Name        Variance Std.Dev.
 niche_name (Intercept) 0.11259  0.3356  
 Residual               0.05278  0.2297  
Number of obs: 536, groups:  niche_name, 268

Fixed effects:
                                     Estimate Std. Error t value
(Intercept)                           0.10521    0.03325   3.164
log(total_species)                    0.19281    0.01685  11.446
percentileTop 20%                     0.13652    0.02657   5.139
log(total_species):percentileTop 20% -0.01304    0.01346  -0.969

Correlation of Fixed Effects:
            (Intr) lg(t_) prT20%
lg(ttl_spc) -0.665              
prcntlTp20% -0.399  0.266       
lg(t_):T20%  0.266 -0.399 -0.665
assign_niche_appearance_factor <- function(dataset) {
  dataset$niche_appearance = '> 20%'
  dataset$niche_appearance[dataset$response_20 > 0] = '10% - 20%'
  dataset$niche_appearance[dataset$response_10 > 0] = '< 10%'
  
  dataset$niche_appearance <- factor(dataset$niche_appearance, levels = c("< 10%", "10% - 20%", "> 20%"))
  dataset
}
merlin_diff_data <- assign_niche_appearance_factor(merlin_diff_data)
ggplot(merlin_diff_data, aes(fill=niche_appearance, y=trophic_niche)) + 
    geom_bar()

load_ever_data <- function(pool) {
  response_name <- paste(pool, 'ever', 'perc', 'ratio', sep = '_')
  dataset <- data_for_response(response_name)
  dataset$present <- 'Yes'
  dataset$present[dataset$response == 0] <- 'No'
  dataset$present <- factor(dataset$present, levels = c("Yes", "No"))
  dataset
}
merlin_ever_data <- load_ever_data('merlin')

── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  niche_name = col_character(),
  foraging_niche = col_character(),
  trophic_niche = col_character(),
  is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
merlin_ever_data
ggplot(merlin_ever_data, aes(fill=present, y=trophic_niche)) + 
    geom_bar()

birdlife_diff_data <- assign_niche_appearance_factor(birdlife_diff_data)
ggplot(birdlife_diff_data, aes(fill=niche_appearance, y=trophic_niche)) + 
    geom_bar()

birdlife_ever_data <- load_ever_data('birdlife')

── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  niche_name = col_character(),
  foraging_niche = col_character(),
  trophic_niche = col_character(),
  is_noctural = col_logical()
)
ℹ Use `spec()` for the full column specifications.
ggplot(merlin_ever_data, aes(fill=present, y=trophic_niche)) + 
    geom_bar()

PCA Variation with presence
ggplot(merlin_ever_data, aes(color = present, x = pc1, y = trophic_niche)) + 
    geom_violin() + geom_jitter(aes(group=present, size = total_species), position=position_jitterdodge()) + theme_bw() +
    theme(legend.position="bottom", legend.title=element_text(size=9), legend.text=element_text(size=8), legend.key.size = unit(1,"line")) +
    guides(color=guide_legend(title="Present in any city?"), size=guide_legend(title="Niche size")) +
    ylab("Trophic Niche") + xlab("PC1: Body size") + labs(title = "Merlin Regional Pool")
ggsave("species_analysis_pc1_merlin.jpg")
Saving 7.29 x 4.51 in image

ggplot(merlin_diff_data, aes(color = niche_appearance, x = pc1, y = trophic_niche)) + 
    geom_violin()
Warning: Groups with fewer than two data points have been dropped.
Warning: Groups with fewer than two data points have been dropped.
Warning: Groups with fewer than two data points have been dropped.
Warning: Groups with fewer than two data points have been dropped.
Warning: Groups with fewer than two data points have been dropped.

ggplot(birdlife_ever_data, aes(color = present, x = pc1, y = trophic_niche)) + 
    geom_violin() + geom_jitter(aes(group=present, size = total_species), position=position_jitterdodge()) + theme_bw() +
    theme(legend.position="bottom", legend.title=element_text(size=9), legend.text=element_text(size=8), legend.key.size = unit(1,"line")) +
    guides(color=guide_legend(title="Present in any city?"), size=guide_legend(title="Niche size")) +
    ylab("Trophic Niche") + xlab("PC1: Body size") + labs(title = "Birdlife Regional Pool")
ggsave("species_analysis_pc1_birdlife.jpg")
First attempt figures

  1. Niches recorded present in at least one city.
  2. Given species ranked by percentage of cities populated given they are present in regional pool; This shows niches present with the top 10% of the most urbanised species (red), the top 20% of the most urbanised species (red + green), and then the remaining niches (blue). This approximates to the niches that would be present in the bottom 25% performing hotspots (red), the bottom 75% performing hotspots (red + green), and then the niches at the highest performing hotspots or niches that are never present (blue).

  1. The redundancy/fullness of the niches that are present in cities with 10% of the most urbanised species, and the redundancy/fullness of the niches that are present in cities with 20% of the most urbanised species.
  2. The percentage increase in redundancy/fullness of niches between the top 10% of most urbanised species and the top 20% of most urbanised species, grouped using Tukey based on an anova of the percentage increase given the tropic niche. This shows the amount of redundancy that is increased from the bottom 25% performing hotspots (hotspots with 10% of regional pool) and the bottom 75% of performing hotspots (hotspots with 20% of regional pool).
jpeg("species_plot1.jpg", width = 800, height = 600)
species_plot1
dev.off()

jpeg("species_plot2.jpg", width = 800, height = 600)
species_plot2
dev.off()
Trophic Niche Accumulation
merlin_accumulation = ggplot(accumulation, aes(x = percent, y = merlin_niche_count)) + 
  geom_line(linetype = "dotted") + 
  geom_line(aes(linetype = merlin_remaining_species), na.value = "dash") +
  scale_linetype_manual(values=c("blank", "solid"), guide = "none") +
  geom_hline(data = . %>% group_by(trophic_niche) %>% filter(merlin_niche_count == max(merlin_niche_count)), aes(yintercept = merlin_niche_count), color = "blue", size = 0.25, linetype = "dashed") +
  theme_bw() +
  theme(legend.position = "bottom", strip.text = element_text(size = 6), axis.text.x = element_text(angle = 90, size = 6),  axis.text.y = element_text(size = 6)) +
  facet_wrap (~ trophic_niche) +
  xlab("Percentage of all Species") + 
  ylab("Number of Niches") +
  labs(title = "Merlin Niche Accumulation")
Warning: Ignoring unknown parameters: na.value
merlin_accumulation

birdlife_accumulation = ggplot(accumulation, aes(x = percent, y = birdlife_niche_count)) + 
  geom_line(linetype = "dotted") + 
  geom_line(aes(linetype = birdlife_remaining_species), na.value = "dash") +
  scale_linetype_manual(values=c("blank", "solid"), guide = "none") +
  geom_hline(data = . %>% group_by(trophic_niche) %>% filter(birdlife_niche_count == max(birdlife_niche_count)), aes(yintercept = birdlife_niche_count), color = "blue", size = 0.25, linetype = "dashed") +
  theme_bw() +
  theme(legend.position = "bottom", strip.text = element_text(size = 6), axis.text.x = element_text(angle = 90, size = 6),  axis.text.y = element_text(size = 6)) +
  facet_wrap (~ trophic_niche) +
  xlab("Percentage of all Species") + 
  ylab("Number of Niches") +
  labs(title = "Birdlife Niche Accumulation")
Warning: Ignoring unknown parameters: na.value
birdlife_accumulation

annotate_figure(
  ggarrange(merlin_accumulation + rremove("xlab") + rremove("ylab"), 
            birdlife_accumulation + rremove("xlab") + rremove("ylab"),
            ncol = 2, label.x = 0),
left = text_grob("Number of Niches Present", rot = 90),
bottom = text_grob("Percentage of all Species - ranked by urbanisation"))


ggsave("trophic_niche_accumlation.jpg")
Saving 7.29 x 4.51 in image

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQpgYGB7cn0KbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShiaWdycXVlcnkpCmxpYnJhcnkoTXVNSW4pCmxpYnJhcnkoZ2dwbG90MikKCmxpYnJhcnkoZ2dwdWJyKQpgYGAKCmBgYHtyfQpyZXNwb25zZSA8LSB0cnkoc3lzdGVtKCd+L2dvb2dsZS1jbG91ZC1zZGsvYmluL2djbG91ZCBwcm9qZWN0cyBsaXN0IC0tcXVpZXQnLCBpbnRlcm4gPSBUKSkKcHJvamVjdGlkIDwtIHN0cnNwbGl0KHJlc3BvbnNlWzJdLCAiICIpW1sxXV1bMV0KYGBgCgpgYGB7cn0Kb3B0aW9ucyhuYS5hY3Rpb24gPSAibmEuZmFpbCIpIApgYGAKCmBgYHtyfQpzb3VyY2UoIi4vZHJlZGdlX2Z1bmN0aW9ucy5SIikKYGBgCgpgYGB7cn0KZHJlZGdlX2FuZF9zdWJzZXQgPC0gZnVuY3Rpb24oZGF0YSkgewogIG1vZGVsIDwtIGxtKAogICAgcmVzcG9uc2UgfiBmb3JhZ2luZ19uaWNoZSArIHRyb3BoaWNfbmljaGUgKyBpc19ub2N0dXJuYWwgKyBwYzEgKyBwYzIgKyBwYzMgKyBwYzQgKyB0b3RhbF9zcGVjaWVzLAogICAgZGF0YT1kYXRhCiAgKQogIGRyZWRnZV9yZXN1bHQgPC0gZHJlZGdlKG1vZGVsKQogIHN1bW1hcnkobW9kZWwuYXZnKGRyZWRnZV9yZXN1bHQsIHN1YnNldCA9IGRlbHRhIDwgMTApKQp9CmBgYAoKYGBge3J9CmxvYWRfbmljaGVfZGF0YSA8LSBmdW5jdGlvbigpIHsKICBmaWxlbmFtZSA8LSAnc3BlY2llc19hbmFseXNpc19jYWNoZS5jc3YnCiAgCiAgaWYgKCFmaWxlLmV4aXN0cyhmaWxlbmFtZSkpIHsKICAgIAogICAgc3FsIDwtICIKICAgICAgICBTRUxFQ1QgCiAgICAgICAgICBuaWNoZV9uYW1lLAogICAgICAgICAgZm9yYWdpbmdfbmljaGUsIAogICAgICAgICAgdHJvcGhpY19uaWNoZSwgCiAgICAgICAgICBpc19ub2N0dXJhbCwgCiAgICAgICAgICB0b3RhbF9zcGVjaWVzLAogICAgICAgICAgbWVybGluXzEwX3BlcmNfcmF0aW8sIAogICAgICAgICAgbWVybGluXzIwX3BlcmNfcmF0aW8sCiAgICAgICAgICBtZXJsaW5fZXZlcl9wZXJjX3JhdGlvLAogICAgICAgICAgYmlyZGxpZmVfMTBfcGVyY19yYXRpbywgCiAgICAgICAgICBiaXJkbGlmZV8yMF9wZXJjX3JhdGlvLAogICAgICAgICAgYmlyZGxpZmVfZXZlcl9wZXJjX3JhdGlvLAogICAgICAgICAgZWl0aGVyXzEwX3BlcmNfcmF0aW8sIAogICAgICAgICAgZWl0aGVyXzIwX3BlcmNfcmF0aW8sIAogICAgICAgICAgZWl0aGVyX2V2ZXJfcGVyY19yYXRpbywKICAgICAgICAgIGJvdGhfMTBfcGVyY19yYXRpbywgCiAgICAgICAgICBib3RoXzIwX3BlcmNfcmF0aW8sCiAgICAgICAgICBib3RoX2V2ZXJfcGVyY19yYXRpbywKICAgICAgICAgIGJvZHlfbW9ycGhzcGFjZS5wYzEubWVhbiBBUyBwYzEsIAogICAgICAgICAgYm9keV9tb3JwaHNwYWNlLnBjMi5tZWFuIEFTIHBjMiwgCiAgICAgICAgICBib2R5X21vcnBoc3BhY2UucGMzLm1lYW4gQVMgcGMzLCAKICAgICAgICAgIGJvZHlfbW9ycGhzcGFjZS5wYzQubWVhbiBBUyBwYzQKICAgICAgICBGUk9NIGBlbmRsZXNzLW1hdHRlci0yOTcyMTQubW9kZWwyLm5pY2hlX2FuYWx5c2lzX21vZGVsYCBMSU1JVCAxMDAwIAogICAgIgogIAogICAgdGIgPC0gYnFfcHJvamVjdF9xdWVyeShwcm9qZWN0aWQsIHNxbCkKCiAgICBkYXRhIDwtIGJxX3RhYmxlX2Rvd25sb2FkKHRiKQogICAgd3JpdGVfY3N2KGRhdGEsIGZpbGVuYW1lKQogIH0KICAKICBkYXRhIDwtIHJlYWRfY3N2KGZpbGVuYW1lKQogIAogIGRhdGFbaXMubmEoZGF0YSRmb3JhZ2luZ19uaWNoZSksXSRmb3JhZ2luZ19uaWNoZSA8LSAnT21uaXZvcmUnCiAgCiAgZGF0YSRmb3JhZ2luZ19uaWNoZSA9IGFzLmZhY3RvcihkYXRhJGZvcmFnaW5nX25pY2hlKQogIGRhdGEkdHJvcGhpY19uaWNoZSA9IGFzLmZhY3RvcihkYXRhJHRyb3BoaWNfbmljaGUpCiAgZGF0YSRpc19ub2N0dXJuYWwgPSBhcy5mYWN0b3IoZGF0YSRpc19ub2N0dXJhbCkKICAKICBkYXRhCn0KCmRhdGFfZm9yX3Jlc3BvbnNlIDwtIGZ1bmN0aW9uKGNvbHVtbl9uYW1lX2Zvcl9yZXNwb25zZSkgewogIGRhdGEgPC0gbG9hZF9uaWNoZV9kYXRhKCkKICBuYW1lcyhkYXRhKVtuYW1lcyhkYXRhKSA9PSBjb2x1bW5fbmFtZV9mb3JfcmVzcG9uc2VdIDwtICJyZXNwb25zZSIKICAKICBkYXRhWyxjKCJuaWNoZV9uYW1lIiwgInJlc3BvbnNlIiwgImZvcmFnaW5nX25pY2hlIiwgInRyb3BoaWNfbmljaGUiLCAiaXNfbm9jdHVybmFsIiwgInBjMSIsICJwYzIiLCAicGMzIiwgInBjNCIsICJ0b3RhbF9zcGVjaWVzIildCn0KYGBgCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KMC4yNSBQZXJjZW50aWxlIC0gMTAlIG9mIHNwZWNpZXMKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpgYGB7cn0KbWVybGluXzEwX2RhdGEgPC0gZGF0YV9mb3JfcmVzcG9uc2UoJ21lcmxpbl8xMF9wZXJjX3JhdGlvJykKbWVybGluXzEwX2RhdGEKYGBgCgoKYGBge3J9Cm1lcmxpbl8xMF9yZXN1bHQgPC0gZHJlZGdlX2FuZF9zdWJzZXQobWVybGluXzEwX2RhdGEpCm1lcmxpbl8xMF9zdW1tIDwtIG1vZGVsX3N1bW1hcnkoJ21lcmxpbl8xMCcsICdzcGVjaWVzJywgbWVybGluXzEwX3Jlc3VsdCkKbWVybGluXzEwX3N1bW0KYGBgCgpgYGB7cn0KYmlyZGxpZmVfMTBfZGF0YSA8LSBkYXRhX2Zvcl9yZXNwb25zZSgnYmlyZGxpZmVfMTBfcGVyY19yYXRpbycpCmJpcmRsaWZlXzEwX3Jlc3VsdCA8LSBkcmVkZ2VfYW5kX3N1YnNldChiaXJkbGlmZV8xMF9kYXRhKQpiaXJkbGlmZV8xMF9zdW1tIDwtIG1vZGVsX3N1bW1hcnkoJ2JpcmRsaWZlXzEwJywgJ3NwZWNpZXMnLCBiaXJkbGlmZV8xMF9yZXN1bHQpCmJpcmRsaWZlXzEwX3N1bW0KYGBgCgoKYGBge3J9CmJvdGhfMTBfZGF0YSA8LSBkYXRhX2Zvcl9yZXNwb25zZSgnYm90aF8xMF9wZXJjX3JhdGlvJykKYm90aF8xMF9yZXN1bHQgPC0gZHJlZGdlX2FuZF9zdWJzZXQoYm90aF8xMF9kYXRhKQpib3RoXzEwX3N1bW0gPC0gbW9kZWxfc3VtbWFyeSgnYm90aF8xMCcsICdzcGVjaWVzJywgYm90aF8xMF9yZXN1bHQpCmJvdGhfMTBfc3VtbQpgYGAKCgpgYGB7cn0KZWl0aGVyXzEwX2RhdGEgPC0gZGF0YV9mb3JfcmVzcG9uc2UoJ2VpdGhlcl8xMF9wZXJjX3JhdGlvJykKZWl0aGVyXzEwX3Jlc3VsdCA8LSBkcmVkZ2VfYW5kX3N1YnNldChlaXRoZXJfMTBfZGF0YSkKZWl0aGVyXzEwX3N1bW0gPC0gbW9kZWxfc3VtbWFyeSgnZWl0aGVyXzEwJywgJ3NwZWNpZXMnLCBlaXRoZXJfMTBfcmVzdWx0KQplaXRoZXJfMTBfc3VtbQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpGdWxsIHJlc3VsdCBmb3IgMTAlIG9mIHNwZWNpZXMKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCmBgYHtyfQphbGxfc3BlY2llc19yZXN1bHRzIDwtIGZ1bGxfam9pbihmdWxsX2pvaW4obWVybGluXzEwX3N1bW0sIGJpcmRsaWZlXzEwX3N1bW0pLCBmdWxsX2pvaW4oYm90aF8xMF9zdW1tLCBlaXRoZXJfMTBfc3VtbSkpCndyaXRlX2NzdihhbGxfc3BlY2llc19yZXN1bHRzLCAic3BlY2llc19hbmFseXNpc19yZXN1bHRfMTBfcGVyYy5jc3YiKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQowLjc1IFBlcmNlbnRpbGUgLSAyMCUgb2Ygc3BlY2llcwotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmBgYHtyfQptZXJsaW5fMjBfZGF0YSA8LSBkYXRhX2Zvcl9yZXNwb25zZSgnbWVybGluXzIwX3BlcmNfcmF0aW8nKQptZXJsaW5fMjBfcmVzdWx0IDwtIGRyZWRnZV9hbmRfc3Vic2V0KG1lcmxpbl8yMF9kYXRhKQptZXJsaW5fMjBfc3VtbSA8LSBtb2RlbF9zdW1tYXJ5KCdtZXJsaW5fMjAnLCAnc3BlY2llcycsIG1lcmxpbl8yMF9yZXN1bHQpCm1lcmxpbl8yMF9zdW1tCmBgYAoKYGBge3J9CmJpcmRsaWZlXzIwX2RhdGEgPC0gZGF0YV9mb3JfcmVzcG9uc2UoJ2JpcmRsaWZlXzIwX3BlcmNfcmF0aW8nKQpiaXJkbGlmZV8yMF9yZXN1bHQgPC0gZHJlZGdlX2FuZF9zdWJzZXQoYmlyZGxpZmVfMjBfZGF0YSkKYmlyZGxpZmVfMjBfc3VtbSA8LSBtb2RlbF9zdW1tYXJ5KCdiaXJkbGlmZV8yMCcsICdzcGVjaWVzJywgYmlyZGxpZmVfMjBfcmVzdWx0KQpiaXJkbGlmZV8yMF9zdW1tCmBgYAoKYGBge3J9CmJvdGhfMjBfZGF0YSA8LSBkYXRhX2Zvcl9yZXNwb25zZSgnYm90aF8yMF9wZXJjX3JhdGlvJykKYm90aF8yMF9yZXN1bHQgPC0gZHJlZGdlX2FuZF9zdWJzZXQoYm90aF8yMF9kYXRhKQpib3RoXzIwX3N1bW0gPC0gbW9kZWxfc3VtbWFyeSgnYm90aF8yMCcsICdzcGVjaWVzJywgYm90aF8yMF9yZXN1bHQpCmJvdGhfMjBfc3VtbQpgYGAKCmBgYHtyfQplaXRoZXJfMjBfZGF0YSA8LSBkYXRhX2Zvcl9yZXNwb25zZSgnZWl0aGVyXzIwX3BlcmNfcmF0aW8nKQplaXRoZXJfMjBfcmVzdWx0IDwtIGRyZWRnZV9hbmRfc3Vic2V0KGVpdGhlcl8yMF9kYXRhKQplaXRoZXJfMjBfc3VtbSA8LSBtb2RlbF9zdW1tYXJ5KCdlaXRoZXJfMjAnLCAnc3BlY2llcycsIGVpdGhlcl8yMF9yZXN1bHQpCmVpdGhlcl8yMF9zdW1tCmBgYAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCkZ1bGwgcmVzdWx0IGZvciAxMCUgb2Ygc3BlY2llcwotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KYGBge3J9CmFsbF9zcGVjaWVzX3Jlc3VsdHMgPC0gZnVsbF9qb2luKGZ1bGxfam9pbihtZXJsaW5fMjBfc3VtbSwgYmlyZGxpZmVfMjBfc3VtbSksIGZ1bGxfam9pbihib3RoXzIwX3N1bW0sIGVpdGhlcl8yMF9zdW1tKSkKd3JpdGVfY3N2KGFsbF9zcGVjaWVzX3Jlc3VsdHMsICJzcGVjaWVzX2FuYWx5c2lzX3Jlc3VsdF8yMF9wZXJjLmNzdiIpCmBgYAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCkNvbXBhcmluZyB0aGUgMiBwZXJjZW50aWxlcwotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmBgYHtyfQpnZ3Bsb3QobWVybGluXzEwX2RhdGEsIGFlcyh4ID0gcmVzcG9uc2UpKSArIGdlb21fYmFyKHdpZHRoID0gMC4xKQpgYGAKCmBgYHtyfQpiaW5kX3NldHMgPC0gZnVuY3Rpb24oZmlyc3RfcGVyY2VudGlsZSwgc2Vjb25kX3BlcmNlbnRpbGUpIHsKICBmaXJzdF9wZXJjZW50aWxlJHBlcmNlbnRpbGUgPC0gIlRvcCAxMCUiCiAgc2Vjb25kX3BlcmNlbnRpbGUkcGVyY2VudGlsZSA8LSAiVG9wIDIwJSIKICByYmluZChmaXJzdF9wZXJjZW50aWxlLCBzZWNvbmRfcGVyY2VudGlsZSkKfQoKbWVybGluX3NwZWNpZXNfZGF0YSA8LSBiaW5kX3NldHMobWVybGluXzEwX2RhdGEsICBtZXJsaW5fMjBfZGF0YSkKYmlyZGxpZmVfc3BlY2llc19kYXRhIDwtIGJpbmRfc2V0cyhiaXJkbGlmZV8xMF9kYXRhLCAgYmlyZGxpZmVfMjBfZGF0YSkKZWl0aGVyX3NwZWNpZXNfZGF0YSA8LSBiaW5kX3NldHMoZWl0aGVyXzEwX2RhdGEsICBlaXRoZXJfMjBfZGF0YSkKYm90aF9zcGVjaWVzX2RhdGEgPC0gYmluZF9zZXRzKGJvdGhfMTBfZGF0YSwgIGJvdGhfMjBfZGF0YSkKYGBgCgpgYGB7cn0KZGlmZl9zZXQgPC0gZnVuY3Rpb24oZmlyc3RfcGVyY2VudGlsZSwgc2Vjb25kX3BlcmNlbnRpbGUpIHsKICBzZWNvbmRfcGVyY2VudGlsZSRyZXNwb25zZV8yMCA8LSBzZWNvbmRfcGVyY2VudGlsZSRyZXNwb25zZQogIAogIHJlc3VsdCA8LSByaWdodF9qb2luKGZpcnN0X3BlcmNlbnRpbGUsIHNlY29uZF9wZXJjZW50aWxlWyxjKCJuaWNoZV9uYW1lIiwgInJlc3BvbnNlXzIwIildLCBieSA9IGMoIm5pY2hlX25hbWUiKSkKICByZXN1bHQkZGlmZiA8LSByZXN1bHQkcmVzcG9uc2VfMjAgLSByZXN1bHQkcmVzcG9uc2UKICByZXN1bHQkaW5jcmVhc2UgPC0gcmVzdWx0JGRpZmYgLyByZXN1bHQkcmVzcG9uc2VfMjAKICByZXN1bHQkaW5jcmVhc2VbaXMubmEocmVzdWx0JGluY3JlYXNlKV0gPSAwCiAgcmVzdWx0JHJlc3BvbnNlXzEwIDwtIHJlc3VsdCRyZXNwb25zZQogIHJlc3VsdFssYygicmVzcG9uc2VfMTAiLCAicmVzcG9uc2VfMjAiLCAiZGlmZiIsICJpbmNyZWFzZSIsICJmb3JhZ2luZ19uaWNoZSIsICJ0cm9waGljX25pY2hlIiwgImlzX25vY3R1cm5hbCIsICJwYzEiLCAicGMyIiwgInBjMyIsICJwYzQiLCAidG90YWxfc3BlY2llcyIpXQp9CgptZXJsaW5fZGlmZl9kYXRhIDwtIGRpZmZfc2V0KG1lcmxpbl8xMF9kYXRhLCAgbWVybGluXzIwX2RhdGEpCmJpcmRsaWZlX2RpZmZfZGF0YSA8LSBkaWZmX3NldChiaXJkbGlmZV8xMF9kYXRhLCAgYmlyZGxpZmVfMjBfZGF0YSkKZWl0aGVyX2RpZmZfZGF0YSA8LSBkaWZmX3NldChlaXRoZXJfMTBfZGF0YSwgIGVpdGhlcl8yMF9kYXRhKQpib3RoX2RpZmZfZGF0YSA8LSBkaWZmX3NldChib3RoXzEwX2RhdGEsICBib3RoXzIwX2RhdGEpCgptZXJsaW5fZGlmZl9kYXRhCmBgYAoKYGBge3J9CmdncGxvdChtZXJsaW5fc3BlY2llc19kYXRhLCBhZXMoeCA9IHJlc3BvbnNlLCB5ID0gdHJvcGhpY19uaWNoZSwgY29sb3IgPSBwZXJjZW50aWxlKSkgKyBnZW9tX2JveHBsb3QoKSArIHRoZW1lX2J3KCkKYGBgCgpgYGB7cn0KbWVybGluX3Ryb3BoaWNfbmljaGVfbmljaGVfYW5vdmEgPC0gYW92KHJlc3BvbnNlfnRyb3BoaWNfbmljaGUgKyBwZXJjZW50aWxlICsgRXJyb3IobmljaGVfbmFtZSksIGRhdGE9bWVybGluX3NwZWNpZXNfZGF0YSkKc3VtbWFyeShtZXJsaW5fdHJvcGhpY19uaWNoZV9uaWNoZV9hbm92YSkKCm1lcmxpbl90cm9waGljX25pY2hlX25pY2hlX2Fub3ZhX2kgPC0gYW92KHJlc3BvbnNlfnRyb3BoaWNfbmljaGUgKiBwZXJjZW50aWxlICsgRXJyb3IobmljaGVfbmFtZSksIGRhdGE9bWVybGluX3NwZWNpZXNfZGF0YSkKc3VtbWFyeShtZXJsaW5fdHJvcGhpY19uaWNoZV9uaWNoZV9hbm92YV9pKQpgYGAKCmBgYHtyfQpwYWlyd2lzZS53aWxjb3gudGVzdChtZXJsaW5fZGlmZl9kYXRhJGluY3JlYXNlLCBtZXJsaW5fZGlmZl9kYXRhJHRyb3BoaWNfbmljaGUpCmBgYApgYGB7cn0KbGlicmFyeShtdWx0Y29tcCkKbWVybGluX2luY3JlYXNlX3Ryb3BpY19uaWNoZV9hbm92YSA8LWFvdihpbmNyZWFzZX50cm9waGljX25pY2hlLCBkYXRhPW1lcmxpbl9kaWZmX2RhdGEpCnN1bW1hcnkobWVybGluX2luY3JlYXNlX3Ryb3BpY19uaWNoZV9hbm92YSkKCm1lcmxpbl9pbmNyZWFzZV90cm9waWNfbmljaGVfdHVrZXkgPC0gY2xkKGdsaHQobWVybGluX2luY3JlYXNlX3Ryb3BpY19uaWNoZV9hbm92YSwgbGluZmN0PW1jcCh0cm9waGljX25pY2hlPSJUdWtleSIpKSkKCm1lcmxpbl9pbmNyZWFzZV90cm9waWNfbmljaGVfdHVrZXkKYGBgCgpgYGB7cn0KcGxvdChtZXJsaW5faW5jcmVhc2VfdHJvcGljX25pY2hlX3R1a2V5KQpgYGAKYGBge3J9CndpdGgudHVrZXkubGFiZWwuYXMuZ3JvdXAgPC0gZnVuY3Rpb24odHVrZXksIGRhdGFzZXQsIGpvaW5fYnkpIHsKICBsYWJlbHMgPC0gZGF0YS5mcmFtZSh0dWtleSRtY2xldHRlcnMkTGV0dGVycykKICBsYWJlbHMkY2F0ZWdvcnkgPC0gcm93bmFtZXMobGFiZWxzKQogIGNvbG5hbWVzKGxhYmVscykgPC0gYygiZ3JvdXAiLCAiY2F0ZWdvcnkiKQogIAogIAogIGxlZnRfam9pbihkYXRhc2V0LCBsYWJlbHMsIGJ5ID0gam9pbl9ieSkKfQpgYGAKCmBgYHtyfQptZXJsaW5fZGlmZl9kYXRhMSA8LSB3aXRoLnR1a2V5LmxhYmVsLmFzLmdyb3VwKG1lcmxpbl9pbmNyZWFzZV90cm9waWNfbmljaGVfdHVrZXksIG1lcmxpbl9kaWZmX2RhdGEsIGMoInRyb3BoaWNfbmljaGUiID0gImNhdGVnb3J5IikpCm1lcmxpbl9kaWZmX2RhdGExCmBgYApgYGB7cn0KdGFibGUobWVybGluX2RpZmZfZGF0YTEkdHJvcGhpY19uaWNoZSkKYGBgCgpgYGB7cn0KZ2dwbG90KG1lcmxpbl9kaWZmX2RhdGExLCBhZXMoeCA9IGluY3JlYXNlLCB5ID0gdHJvcGhpY19uaWNoZSwgY29sb3IgPSBncm91cCkpICsgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZV9idygpCmBgYAoKYGBge3J9CmdncGxvdChiaXJkbGlmZV9zcGVjaWVzX2RhdGEsIGFlcyh4ID0gcmVzcG9uc2UsIHkgPSB0cm9waGljX25pY2hlLCBjb2xvciA9IHBlcmNlbnRpbGUpKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWVfYncoKQpgYGAKCmBgYHtyfQpiaXJkbGlmZV90cm9waGljX25pY2hlX25pY2hlX2Fub3ZhIDwtIGFvdihyZXNwb25zZX50cm9waGljX25pY2hlICsgcGVyY2VudGlsZSArIEVycm9yKG5pY2hlX25hbWUpLCBkYXRhPWJpcmRsaWZlX3NwZWNpZXNfZGF0YSkKc3VtbWFyeShiaXJkbGlmZV90cm9waGljX25pY2hlX25pY2hlX2Fub3ZhKQoKYmlyZGxpZmVfdHJvcGhpY19uaWNoZV9uaWNoZV9hbm92YV9pIDwtIGFvdihyZXNwb25zZX50cm9waGljX25pY2hlICogcGVyY2VudGlsZSArIEVycm9yKG5pY2hlX25hbWUpLCBkYXRhPWJpcmRsaWZlX3NwZWNpZXNfZGF0YSkKc3VtbWFyeShiaXJkbGlmZV90cm9waGljX25pY2hlX25pY2hlX2Fub3ZhX2kpCmBgYAoKYGBge3J9CmJpcmRsaWZlX2luY3JlYXNlX3Ryb3BpY19uaWNoZV9hbm92YSA8LWFvdihpbmNyZWFzZX50cm9waGljX25pY2hlLCBkYXRhPWJpcmRsaWZlX2RpZmZfZGF0YSkKc3VtbWFyeShiaXJkbGlmZV9pbmNyZWFzZV90cm9waWNfbmljaGVfYW5vdmEpCgpiaXJkbGlmZV9pbmNyZWFzZV90cm9waWNfbmljaGVfdHVrZXkgPC0gY2xkKGdsaHQoYmlyZGxpZmVfaW5jcmVhc2VfdHJvcGljX25pY2hlX2Fub3ZhLCBsaW5mY3Q9bWNwKHRyb3BoaWNfbmljaGU9IlR1a2V5IikpKQoKYmlyZGxpZmVfaW5jcmVhc2VfdHJvcGljX25pY2hlX3R1a2V5CmBgYAoKYGBge3J9CmJpcmRsaWZlX2RpZmZfZGF0YTEgPC0gd2l0aC50dWtleS5sYWJlbC5hcy5ncm91cChiaXJkbGlmZV9pbmNyZWFzZV90cm9waWNfbmljaGVfdHVrZXksIGJpcmRsaWZlX2RpZmZfZGF0YSwgYygidHJvcGhpY19uaWNoZSIgPSAiY2F0ZWdvcnkiKSkKZ2dwbG90KGJpcmRsaWZlX2RpZmZfZGF0YTEsIGFlcyh4ID0gaW5jcmVhc2UsIHkgPSB0cm9waGljX25pY2hlLCBjb2xvciA9IGdyb3VwKSkgKyBnZW9tX2JveHBsb3QoKSArIHRoZW1lX2J3KCkKYGBgCgpgYGB7cn0KZ2dwbG90KGVpdGhlcl9zcGVjaWVzX2RhdGEsIGFlcyh4ID0gcmVzcG9uc2UsIHkgPSB0cm9waGljX25pY2hlLCBjb2xvciA9IHBlcmNlbnRpbGUpKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWVfYncoKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoYm90aF9zcGVjaWVzX2RhdGEsIGFlcyh4ID0gcmVzcG9uc2UsIHkgPSB0cm9waGljX25pY2hlLCBjb2xvciA9IHBlcmNlbnRpbGUpKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWVfYncoKQpgYGAKCmBgYHtyfQpucm93KG1lcmxpbl8xMF9kYXRhW21lcmxpbl8xMF9kYXRhJHJlc3BvbnNlID4gMCxdKQpucm93KG1lcmxpbl8yMF9kYXRhW21lcmxpbl8yMF9kYXRhJHJlc3BvbnNlID4gMCxdKQpgYGAKCmBgYHtyfQpucm93KGJpcmRsaWZlXzEwX2RhdGFbYmlyZGxpZmVfMTBfZGF0YSRyZXNwb25zZSA+IDAsXSkKbnJvdyhiaXJkbGlmZV8yMF9kYXRhW2JpcmRsaWZlXzIwX2RhdGEkcmVzcG9uc2UgPiAwLF0pCmBgYAoKYGBge3J9Cm5yb3coZWl0aGVyXzEwX2RhdGFbZWl0aGVyXzEwX2RhdGEkcmVzcG9uc2UgPiAwLF0pCm5yb3coZWl0aGVyXzIwX2RhdGFbZWl0aGVyXzIwX2RhdGEkcmVzcG9uc2UgPiAwLF0pCmBgYAoKYGBge3J9Cm5yb3coYm90aF8xMF9kYXRhW2JvdGhfMTBfZGF0YSRyZXNwb25zZSA+IDAsXSkKbnJvdyhib3RoXzIwX2RhdGFbYm90aF8yMF9kYXRhJHJlc3BvbnNlID4gMCxdKQpgYGAKCmBgYHtyfQpnZ3Bsb3QobWVybGluX3NwZWNpZXNfZGF0YSwgYWVzKHggPSByZXNwb25zZSwgeSA9IGZvcmFnaW5nX25pY2hlLCBjb2xvciA9IHBlcmNlbnRpbGUpKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWVfYncoKQpgYGAKCmBgYHtyfQppbnRlcmFjdGlvbi5wbG90KG1lcmxpbl9zcGVjaWVzX2RhdGEkZm9yYWdpbmdfbmljaGUsIG1lcmxpbl9zcGVjaWVzX2RhdGEkcGVyY2VudGlsZSwgbWVybGluX3NwZWNpZXNfZGF0YSRyZXNwb25zZSkKYGBgCgpgYGB7cn0KbWVybGluX2ZvcmFnaW5nX25pY2hlX2Fub3ZhIDwtIGFvdihyZXNwb25zZX5mb3JhZ2luZ19uaWNoZSArIHBlcmNlbnRpbGUgKyBFcnJvcihuaWNoZV9uYW1lKSwgZGF0YT1tZXJsaW5fc3BlY2llc19kYXRhKQpzdW1tYXJ5KG1lcmxpbl9mb3JhZ2luZ19uaWNoZV9hbm92YSkKCm1lcmxpbl9mb3JhZ2luZ19uaWNoZV9hbm92YV9pIDwtIGFvdihyZXNwb25zZX5mb3JhZ2luZ19uaWNoZSAqIHBlcmNlbnRpbGUgKyBFcnJvcihuaWNoZV9uYW1lKSwgZGF0YT1tZXJsaW5fc3BlY2llc19kYXRhKQpzdW1tYXJ5KG1lcmxpbl9mb3JhZ2luZ19uaWNoZV9hbm92YV9pKQpgYGAKCgoKYGBge3J9CmdncGxvdChiaXJkbGlmZV9zcGVjaWVzX2RhdGEsIGFlcyh4ID0gcmVzcG9uc2UsIHkgPSBmb3JhZ2luZ19uaWNoZSwgY29sb3IgPSBwZXJjZW50aWxlKSkgKyBnZW9tX2JveHBsb3QoKSArIHRoZW1lX2J3KCkKYGBgCgpgYGB7cn0KYmlyZGxpZmVfZm9yYWdpbmdfbmljaGVfYW5vdmEgPC0gYW92KHJlc3BvbnNlfmZvcmFnaW5nX25pY2hlICsgcGVyY2VudGlsZSArIEVycm9yKG5pY2hlX25hbWUpLCBkYXRhPWJpcmRsaWZlX3NwZWNpZXNfZGF0YSkKc3VtbWFyeShiaXJkbGlmZV9mb3JhZ2luZ19uaWNoZV9hbm92YSkKCmJpcmRsaWZlX2ZvcmFnaW5nX25pY2hlX2Fub3ZhX2kgPC0gYW92KHJlc3BvbnNlfmZvcmFnaW5nX25pY2hlICogcGVyY2VudGlsZSArIEVycm9yKG5pY2hlX25hbWUpLCBkYXRhPWJpcmRsaWZlX3NwZWNpZXNfZGF0YSkKc3VtbWFyeShiaXJkbGlmZV9mb3JhZ2luZ19uaWNoZV9hbm92YV9pKQpgYGAKCgpgYGB7cn0KcGNfYXhpc19maWd1cmUgPC0gZnVuY3Rpb24oZGF0YXNldCkgewogIGFubm90YXRlX2ZpZ3VyZSgKZ2dhcnJhbmdlKAogIGdncGxvdChkYXRhc2V0LCBhZXMoeCA9IHBjMSwgeSA9IGxvZyhyZXNwb25zZSksIGNvbG9yID0gcGVyY2VudGlsZSkpICsgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKyBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSArIHRoZW1lX2J3KCkgKyBycmVtb3ZlKCJ5bGFiIiksCiAgZ2dwbG90KGRhdGFzZXQsIGFlcyh4ID0gcGMyLCB5ID0gbG9nKHJlc3BvbnNlKSwgY29sb3IgPSBwZXJjZW50aWxlKSkgKyBnZW9tX3BvaW50KGFscGhhID0gMC41KSArIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsgdGhlbWVfYncoKSArIHJyZW1vdmUoInlsYWIiKSwKICBnZ3Bsb3QoZGF0YXNldCwgYWVzKHggPSBwYzMsIHkgPSBsb2cocmVzcG9uc2UpLCBjb2xvciA9IHBlcmNlbnRpbGUpKSArIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSkgKyB0aGVtZV9idygpICsgcnJlbW92ZSgieWxhYiIpLAogIGdncGxvdChkYXRhc2V0LCBhZXMoeCA9IHBjNCwgeSA9IGxvZyhyZXNwb25zZSksIGNvbG9yID0gcGVyY2VudGlsZSkpICsgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKyBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSArIHRoZW1lX2J3KCkgKyBycmVtb3ZlKCJ5bGFiIiksCiAgbnJvdyA9IDIsIG5jb2wgPSAyLCBjb21tb24ubGVnZW5kID0gVCwgbGFiZWwueCA9IDApLApsZWZ0ID0gdGV4dF9ncm9iKCJsb2cocmVzcG9uc2UpIiwgcm90ID0gOTApKQp9CmBgYAoKCmBgYHtyfQpwY19heGlzX2ZpZ3VyZShtZXJsaW5fc3BlY2llc19kYXRhKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGxtZTQpCm1lcmxpbl9wYzFfbW9kZWwgPSBsbWVyKHJlc3BvbnNlIH4gcGMxICogcGVyY2VudGlsZSArICgxfG5pY2hlX25hbWUpLCBkYXRhPW1lcmxpbl9zcGVjaWVzX2RhdGEpCmFub3ZhKG1lcmxpbl9wYzFfbW9kZWwpCnN1bW1hcnkobWVybGluX3BjMV9tb2RlbCkKYGBgCgpgYGB7cn0KbWVybGluX3BjMl9tb2RlbCA9IGxtZXIocmVzcG9uc2UgfiBwYzIgKiBwZXJjZW50aWxlICsgKDF8bmljaGVfbmFtZSksIGRhdGE9bWVybGluX3NwZWNpZXNfZGF0YSkKYW5vdmEobWVybGluX3BjMl9tb2RlbCkKc3VtbWFyeShtZXJsaW5fcGMyX21vZGVsKQpgYGAKCmBgYHtyfQptZXJsaW5fcGMzX21vZGVsID0gbG1lcihyZXNwb25zZSB+IHBjMyAqIHBlcmNlbnRpbGUgKyAoMXxuaWNoZV9uYW1lKSwgZGF0YT1tZXJsaW5fc3BlY2llc19kYXRhKQphbm92YShtZXJsaW5fcGMzX21vZGVsKQpzdW1tYXJ5KG1lcmxpbl9wYzNfbW9kZWwpCmBgYAoKYGBge3J9Cm1lcmxpbl9wYzRfbW9kZWwgPSBsbWVyKHJlc3BvbnNlIH4gcGM0ICogcGVyY2VudGlsZSArICgxfG5pY2hlX25hbWUpLCBkYXRhPW1lcmxpbl9zcGVjaWVzX2RhdGEpCmFub3ZhKG1lcmxpbl9wYzRfbW9kZWwpCnN1bW1hcnkobWVybGluX3BjNF9tb2RlbCkKYGBgCgpgYGB7cn0KcGNfYXhpc19maWd1cmUoYmlyZGxpZmVfc3BlY2llc19kYXRhKQpgYGAKCmBgYHtyfQpnZ3Bsb3QobWVybGluX3NwZWNpZXNfZGF0YSwgYWVzKHggPSByZXNwb25zZSwgeSA9IGlzX25vY3R1cm5hbCwgY29sb3IgPSBwZXJjZW50aWxlKSkgKyBnZW9tX2JveHBsb3QoKSArIHRoZW1lX2J3KCkKYGBgCgpgYGB7cn0KbWVybGluX25vY3R1cm5hbF9hbm92YSA8LSBhb3YocmVzcG9uc2V+aXNfbm9jdHVybmFsICsgcGVyY2VudGlsZSArIEVycm9yKG5pY2hlX25hbWUpLCBkYXRhPW1lcmxpbl9zcGVjaWVzX2RhdGEpCnN1bW1hcnkobWVybGluX25vY3R1cm5hbF9hbm92YSkKCm1lcmxpbl9ub2N0dXJuYWxfYW5vdmFfaSA8LSBhb3YocmVzcG9uc2V+aXNfbm9jdHVybmFsICogcGVyY2VudGlsZSArIEVycm9yKG5pY2hlX25hbWUpLCBkYXRhPW1lcmxpbl9zcGVjaWVzX2RhdGEpCnN1bW1hcnkobWVybGluX25vY3R1cm5hbF9hbm92YV9pKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoYmlyZGxpZmVfc3BlY2llc19kYXRhLCBhZXMoeCA9IHJlc3BvbnNlLCB5ID0gaXNfbm9jdHVybmFsLCBjb2xvciA9IHBlcmNlbnRpbGUpKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWVfYncoKQpgYGAKCmBgYHtyfQpiaXJkbGlmZV9ub2N0dXJuYWxfYW5vdmEgPC0gYW92KHJlc3BvbnNlfmlzX25vY3R1cm5hbCArIHBlcmNlbnRpbGUgKyBFcnJvcihuaWNoZV9uYW1lKSwgZGF0YT1iaXJkbGlmZV9zcGVjaWVzX2RhdGEpCnN1bW1hcnkoYmlyZGxpZmVfbm9jdHVybmFsX2Fub3ZhKQoKYmlyZGxpZmVfbm9jdHVybmFsX2Fub3ZhX2kgPC0gYW92KHJlc3BvbnNlfmlzX25vY3R1cm5hbCAqIHBlcmNlbnRpbGUgKyBFcnJvcihuaWNoZV9uYW1lKSwgZGF0YT1iaXJkbGlmZV9zcGVjaWVzX2RhdGEpCnN1bW1hcnkoYmlyZGxpZmVfbm9jdHVybmFsX2Fub3ZhX2kpCmBgYAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KSW52ZXN0aWdhdGlvbiBvZiBwZXJjZW50aWxlcyBhbmQgcHJlc2VuY2UKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmBgYHtyfQpnZ3Bsb3QobWVybGluX3NwZWNpZXNfZGF0YSwgYWVzKHggPSB0b3RhbF9zcGVjaWVzLCB5ID0gbG9nKHJlc3BvbnNlKSwgY29sb3IgPSBwZXJjZW50aWxlKSkgKyBnZW9tX3BvaW50KGFscGhhID0gMC41KSArIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsgdGhlbWVfYncoKQpgYGAKCmBgYHtyfQptZXJsaW5fc3BlY2llc19jb3VudF9tb2RlbCA9IGxtZXIocmVzcG9uc2UgfiB0b3RhbF9zcGVjaWVzICogcGVyY2VudGlsZSArICgxfG5pY2hlX25hbWUpLCBkYXRhPW1lcmxpbl9zcGVjaWVzX2RhdGEpCmFub3ZhKG1lcmxpbl9zcGVjaWVzX2NvdW50X21vZGVsKQpzdW1tYXJ5KG1lcmxpbl9zcGVjaWVzX2NvdW50X21vZGVsKQpgYGAKCmBgYHtyfQpiaXJkbGlmZV9zcGVjaWVzX2NvdW50X21vZGVsID0gbG1lcihyZXNwb25zZSB+IHRvdGFsX3NwZWNpZXMgKiBwZXJjZW50aWxlICsgKDF8bmljaGVfbmFtZSksIGRhdGE9YmlyZGxpZmVfc3BlY2llc19kYXRhKQphbm92YShiaXJkbGlmZV9zcGVjaWVzX2NvdW50X21vZGVsKQpzdW1tYXJ5KGJpcmRsaWZlX3NwZWNpZXNfY291bnRfbW9kZWwpCmBgYAoKYGBge3J9Cm1lcmxpbl9zcGVjaWVzX2RhdGEkcHJlc2VudCA8LSBtZXJsaW5fc3BlY2llc19kYXRhJHJlc3BvbnNlID4gMApgYGAKCmBgYHtyfQpnZ3Bsb3QobWVybGluX3NwZWNpZXNfZGF0YSwgYWVzKHggPSBsb2codG90YWxfc3BlY2llcyksIHkgPSBwcmVzZW50LCBjb2xvciA9IHBlcmNlbnRpbGUpKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWVfYncoKQpgYGAKCgpgYGB7cn0KbWVybGluX3ByZXNlbnRfbW9kZWwgPSBsbWVyKHByZXNlbnQgfiBsb2codG90YWxfc3BlY2llcykgKiBwZXJjZW50aWxlICsgKDF8bmljaGVfbmFtZSksIGRhdGE9bWVybGluX3NwZWNpZXNfZGF0YSkKYW5vdmEobWVybGluX3ByZXNlbnRfbW9kZWwpCnN1bW1hcnkobWVybGluX3ByZXNlbnRfbW9kZWwpCmBgYAoKYGBge3J9CmFzc2lnbl9uaWNoZV9hcHBlYXJhbmNlX2ZhY3RvciA8LSBmdW5jdGlvbihkYXRhc2V0KSB7CiAgZGF0YXNldCRuaWNoZV9hcHBlYXJhbmNlID0gJz4gMjAlJwogIGRhdGFzZXQkbmljaGVfYXBwZWFyYW5jZVtkYXRhc2V0JHJlc3BvbnNlXzIwID4gMF0gPSAnMTAlIC0gMjAlJwogIGRhdGFzZXQkbmljaGVfYXBwZWFyYW5jZVtkYXRhc2V0JHJlc3BvbnNlXzEwID4gMF0gPSAnPCAxMCUnCiAgCiAgZGF0YXNldCRuaWNoZV9hcHBlYXJhbmNlIDwtIGZhY3RvcihkYXRhc2V0JG5pY2hlX2FwcGVhcmFuY2UsIGxldmVscyA9IGMoIjwgMTAlIiwgIjEwJSAtIDIwJSIsICI+IDIwJSIpKQogIGRhdGFzZXQKfQpgYGAKCmBgYHtyfQptZXJsaW5fZGlmZl9kYXRhIDwtIGFzc2lnbl9uaWNoZV9hcHBlYXJhbmNlX2ZhY3RvcihtZXJsaW5fZGlmZl9kYXRhKQpgYGAKCgpgYGB7cn0KZ2dwbG90KG1lcmxpbl9kaWZmX2RhdGEsIGFlcyhmaWxsPW5pY2hlX2FwcGVhcmFuY2UsIHk9dHJvcGhpY19uaWNoZSkpICsgCiAgICBnZW9tX2JhcigpCmBgYAoKYGBge3J9CmxvYWRfZXZlcl9kYXRhIDwtIGZ1bmN0aW9uKHBvb2wpIHsKICByZXNwb25zZV9uYW1lIDwtIHBhc3RlKHBvb2wsICdldmVyJywgJ3BlcmMnLCAncmF0aW8nLCBzZXAgPSAnXycpCiAgZGF0YXNldCA8LSBkYXRhX2Zvcl9yZXNwb25zZShyZXNwb25zZV9uYW1lKQogIGRhdGFzZXQkcHJlc2VudCA8LSAnWWVzJwogIGRhdGFzZXQkcHJlc2VudFtkYXRhc2V0JHJlc3BvbnNlID09IDBdIDwtICdObycKICBkYXRhc2V0JHByZXNlbnQgPC0gZmFjdG9yKGRhdGFzZXQkcHJlc2VudCwgbGV2ZWxzID0gYygiWWVzIiwgIk5vIikpCiAgZGF0YXNldAp9CmBgYAoKYGBge3J9Cm1lcmxpbl9ldmVyX2RhdGEgPC0gbG9hZF9ldmVyX2RhdGEoJ21lcmxpbicpCm1lcmxpbl9ldmVyX2RhdGEKYGBgCgpgYGB7cn0KZ2dwbG90KG1lcmxpbl9ldmVyX2RhdGEsIGFlcyhmaWxsPXByZXNlbnQsIHk9dHJvcGhpY19uaWNoZSkpICsgCiAgICBnZW9tX2JhcigpCmBgYApgYGB7cn0KYmlyZGxpZmVfZGlmZl9kYXRhIDwtIGFzc2lnbl9uaWNoZV9hcHBlYXJhbmNlX2ZhY3RvcihiaXJkbGlmZV9kaWZmX2RhdGEpCmBgYAoKCmBgYHtyfQpnZ3Bsb3QoYmlyZGxpZmVfZGlmZl9kYXRhLCBhZXMoZmlsbD1uaWNoZV9hcHBlYXJhbmNlLCB5PXRyb3BoaWNfbmljaGUpKSArIAogICAgZ2VvbV9iYXIoKQpgYGAKCgpgYGB7cn0KYmlyZGxpZmVfZXZlcl9kYXRhIDwtIGxvYWRfZXZlcl9kYXRhKCdiaXJkbGlmZScpCmBgYAoKYGBge3J9CmdncGxvdChtZXJsaW5fZXZlcl9kYXRhLCBhZXMoZmlsbD1wcmVzZW50LCB5PXRyb3BoaWNfbmljaGUpKSArIAogICAgZ2VvbV9iYXIoKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KUENBIFZhcmlhdGlvbiB3aXRoIHByZXNlbmNlCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCgpgYGB7cn0KZ2dwbG90KG1lcmxpbl9ldmVyX2RhdGEsIGFlcyhjb2xvciA9IHByZXNlbnQsIHggPSBwYzEsIHkgPSB0cm9waGljX25pY2hlKSkgKyAKICAgIGdlb21fdmlvbGluKCkgKyBnZW9tX2ppdHRlcihhZXMoZ3JvdXA9cHJlc2VudCwgc2l6ZSA9IHRvdGFsX3NwZWNpZXMpLCBwb3NpdGlvbj1wb3NpdGlvbl9qaXR0ZXJkb2RnZSgpKSArIHRoZW1lX2J3KCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OSksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTgpLCBsZWdlbmQua2V5LnNpemUgPSB1bml0KDEsImxpbmUiKSkgKwogICAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZCh0aXRsZT0iUHJlc2VudCBpbiBhbnkgY2l0eT8iKSwgc2l6ZT1ndWlkZV9sZWdlbmQodGl0bGU9Ik5pY2hlIHNpemUiKSkgKwogICAgeWxhYigiVHJvcGhpYyBOaWNoZSIpICsgeGxhYigiUEMxOiBCb2R5IHNpemUiKSArIGxhYnModGl0bGUgPSAiTWVybGluIFJlZ2lvbmFsIFBvb2wiKQpnZ3NhdmUoInNwZWNpZXNfYW5hbHlzaXNfcGMxX21lcmxpbi5qcGciKQpgYGAKYGBge3J9CmdncGxvdChtZXJsaW5fZGlmZl9kYXRhLCBhZXMoY29sb3IgPSBuaWNoZV9hcHBlYXJhbmNlLCB4ID0gcGMxLCB5ID0gdHJvcGhpY19uaWNoZSkpICsgCiAgICBnZW9tX3Zpb2xpbigpCmBgYAoKCmBgYHtyfQpnZ3Bsb3QobWVybGluX2V2ZXJfZGF0YSwgYWVzKGNvbG9yID0gcHJlc2VudCwgeCA9IHBjMiwgeSA9IHRyb3BoaWNfbmljaGUpKSArIAogICAgZ2VvbV92aW9saW4oKQpgYGAKYGBge3J9CmdncGxvdChtZXJsaW5fZXZlcl9kYXRhLCBhZXMoY29sb3IgPSBwcmVzZW50LCB4ID0gcGMzLCB5ID0gdHJvcGhpY19uaWNoZSkpICsgCiAgICBnZW9tX3Zpb2xpbigpCmBgYApgYGB7cn0KZ2dwbG90KG1lcmxpbl9ldmVyX2RhdGEsIGFlcyhjb2xvciA9IHByZXNlbnQsIHggPSBwYzQsIHkgPSB0cm9waGljX25pY2hlKSkgKyAKICAgIGdlb21fdmlvbGluKCkKYGBgCgoKYGBge3J9CmdncGxvdChiaXJkbGlmZV9ldmVyX2RhdGEsIGFlcyhjb2xvciA9IHByZXNlbnQsIHggPSBwYzEsIHkgPSB0cm9waGljX25pY2hlKSkgKyAKICAgIGdlb21fdmlvbGluKCkgKyBnZW9tX2ppdHRlcihhZXMoZ3JvdXA9cHJlc2VudCwgc2l6ZSA9IHRvdGFsX3NwZWNpZXMpLCBwb3NpdGlvbj1wb3NpdGlvbl9qaXR0ZXJkb2RnZSgpKSArIHRoZW1lX2J3KCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OSksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTgpLCBsZWdlbmQua2V5LnNpemUgPSB1bml0KDEsImxpbmUiKSkgKwogICAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZCh0aXRsZT0iUHJlc2VudCBpbiBhbnkgY2l0eT8iKSwgc2l6ZT1ndWlkZV9sZWdlbmQodGl0bGU9Ik5pY2hlIHNpemUiKSkgKwogICAgeWxhYigiVHJvcGhpYyBOaWNoZSIpICsgeGxhYigiUEMxOiBCb2R5IHNpemUiKSArIGxhYnModGl0bGUgPSAiQmlyZGxpZmUgUmVnaW9uYWwgUG9vbCIpCmdnc2F2ZSgic3BlY2llc19hbmFseXNpc19wYzFfYmlyZGxpZmUuanBnIikKYGBgCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KRmlyc3QgYXR0ZW1wdCBmaWd1cmVzCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmBgYHtyfQp0aGVtZSA8LSAgdGhlbWVfYncoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIiwgbGVnZW5kLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTkpLCBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT04KSwgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsImxpbmUiKSkKZ3VpZGVfZXZlciA8LSBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQodGl0bGU9IlByZXNlbnQgaW4gYW55IGNpdHk/IikpCmd1aWRlX3BlcmNlbnRpbGUgPC0gZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJUb3AgWCUgb2YgcmFua2VkIHNwZWNpZXMiLCBucm93ID0gMykpCgpzcGVjaWVzX3Bsb3QxIDwtIGFubm90YXRlX2ZpZ3VyZSgKICBnZ2FycmFuZ2UoCiAgICBnZ3Bsb3QobWVybGluX2V2ZXJfZGF0YSwgYWVzKGZpbGw9cHJlc2VudCwgeT10cm9waGljX25pY2hlKSkgKyBnZW9tX2JhcigpICsgdGhlbWUgKyBndWlkZV9ldmVyICsgcnJlbW92ZSgieGxhYiIpICsgcnJlbW92ZSgieWxhYiIpICsgbGFicyh0aXRsZSA9ICJNZXJsaW4iKSwKICAgIGdncGxvdChiaXJkbGlmZV9ldmVyX2RhdGEsIGFlcyhmaWxsPXByZXNlbnQsIHk9dHJvcGhpY19uaWNoZSkpICsgZ2VvbV9iYXIoKSArIHRoZW1lICsgZ3VpZGVfZXZlciArIHJyZW1vdmUoInhsYWIiKSArIHJyZW1vdmUoInlsYWIiKSArIGxhYnModGl0bGUgPSAiQmlyZGxpZmUiKSwKICAgIGdncGxvdChtZXJsaW5fZGlmZl9kYXRhLCBhZXMoZmlsbD1uaWNoZV9hcHBlYXJhbmNlLCB5PXRyb3BoaWNfbmljaGUpKSArICBnZW9tX2JhcigpKyB0aGVtZSArIGd1aWRlX3BlcmNlbnRpbGUgKyBycmVtb3ZlKCJ4bGFiIikgKyBycmVtb3ZlKCJ5bGFiIiksCiAgICBnZ3Bsb3QoYmlyZGxpZmVfZGlmZl9kYXRhLCBhZXMoZmlsbD1uaWNoZV9hcHBlYXJhbmNlLCB5PXRyb3BoaWNfbmljaGUpKSArIGdlb21fYmFyKCkgKyB0aGVtZSArIGd1aWRlX3BlcmNlbnRpbGUgKyBycmVtb3ZlKCJ4bGFiIikgKyBycmVtb3ZlKCJ5bGFiIiksCiAgICBucm93ID0gMiwgbmNvbCA9IDIsIGNvbW1vbi5sZWdlbmQgPSBGLCBsYWJlbC54ID0gMCwgbGFiZWxzID0gYygiYSkiLCAiIiwgImIpIiwgIiIpKSwKbGVmdCA9IHRleHRfZ3JvYigiVHJvcGhpYyBOaWNoZSIsIHJvdCA9IDkwKSwKYm90dG9tID0gdGV4dF9ncm9iKCJOaWNoZSBDb3VudCIpKQoKc3BlY2llc19wbG90MQpgYGAKYSkgTmljaGVzIHJlY29yZGVkIHByZXNlbnQgaW4gYXQgbGVhc3Qgb25lIGNpdHkuCmIpIEdpdmVuIHNwZWNpZXMgcmFua2VkIGJ5IHBlcmNlbnRhZ2Ugb2YgY2l0aWVzIHBvcHVsYXRlZCBnaXZlbiB0aGV5IGFyZSBwcmVzZW50IGluIHJlZ2lvbmFsIHBvb2w7IFRoaXMgc2hvd3MgbmljaGVzIHByZXNlbnQgd2l0aCB0aGUgdG9wIDEwJSBvZiB0aGUgbW9zdCB1cmJhbmlzZWQgc3BlY2llcyAocmVkKSwgdGhlIHRvcCAyMCUgb2YgdGhlIG1vc3QgdXJiYW5pc2VkIHNwZWNpZXMgKHJlZCArIGdyZWVuKSwgYW5kIHRoZW4gdGhlIHJlbWFpbmluZyBuaWNoZXMgKGJsdWUpLiBUaGlzIGFwcHJveGltYXRlcyB0byB0aGUgbmljaGVzIHRoYXQgd291bGQgYmUgcHJlc2VudCBpbiB0aGUgYm90dG9tIDI1JSBwZXJmb3JtaW5nIGhvdHNwb3RzIChyZWQpLCB0aGUgYm90dG9tIDc1JSBwZXJmb3JtaW5nIGhvdHNwb3RzIChyZWQgKyBncmVlbiksIGFuZCB0aGVuIHRoZSBuaWNoZXMgYXQgdGhlIGhpZ2hlc3QgcGVyZm9ybWluZyBob3RzcG90cyBvciBuaWNoZXMgdGhhdCBhcmUgbmV2ZXIgcHJlc2VudCAoYmx1ZSkuCgpgYGB7cn0KZ3VpZGVfcGVyY2VudGlsZV8yIDwtIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQodGl0bGU9IlBlcmNlbnRpbGUiKSkKZ3VpZGVfaW5jcmVhc2UgPC0gZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZCh0aXRsZT0iVHVrZXkgcmVzcG9uc2UgZ3JvdXAiLCBucm93ID0gMikpCgpzcGVjaWVzX3Bsb3QyIDwtIGFubm90YXRlX2ZpZ3VyZSgKICBnZ2FycmFuZ2UoCiAgICBnZ3Bsb3QobWVybGluX3NwZWNpZXNfZGF0YSwgYWVzKHggPSByZXNwb25zZSwgeSA9IHRyb3BoaWNfbmljaGUsIGNvbG9yID0gcGVyY2VudGlsZSkpICsgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZSAgKyBndWlkZV9wZXJjZW50aWxlXzIgKyB4bGFiKCJGdWxsbmVzcyIpICsgcnJlbW92ZSgieWxhYiIpICsgbGFicyh0aXRsZSA9ICJNZXJsaW4iKSwKICAgIGdncGxvdChiaXJkbGlmZV9zcGVjaWVzX2RhdGEsIGFlcyh4ID0gcmVzcG9uc2UsIHkgPSB0cm9waGljX25pY2hlLCBjb2xvciA9IHBlcmNlbnRpbGUpKSArIGdlb21fYm94cGxvdCgpICsgdGhlbWUgKyBndWlkZV9wZXJjZW50aWxlXzIgKyB4bGFiKCJGdWxsbmVzcyIpICsgcnJlbW92ZSgieWxhYiIpICsgbGFicyh0aXRsZSA9ICJCaXJkbGlmZSIpLAogICAgZ2dwbG90KG1lcmxpbl9kaWZmX2RhdGExLCBhZXMoeCA9IGluY3JlYXNlLCB5ID0gdHJvcGhpY19uaWNoZSwgY29sb3IgPSBncm91cCkpICsgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZSArIGd1aWRlX2luY3JlYXNlICsgeGxhYigiSW5jcmVhc2UgaW4gZnVsbG5lc3MiKSArIHJyZW1vdmUoInlsYWIiKSwKICAgIGdncGxvdChiaXJkbGlmZV9kaWZmX2RhdGExLCBhZXMoeCA9IGluY3JlYXNlLCB5ID0gdHJvcGhpY19uaWNoZSwgY29sb3IgPSBncm91cCkpICsgZ2VvbV9ib3hwbG90KCkgKyB0aGVtZSArIGd1aWRlX2luY3JlYXNlICsgeGxhYigiSW5jcmVhc2UgaW4gZnVsbG5lc3MiKSArIHJyZW1vdmUoInlsYWIiKSwgCiAgICBucm93ID0gMiwgbmNvbCA9IDIsIGNvbW1vbi5sZWdlbmQgPSBGLCBsYWJlbC54ID0gMCwgbGFiZWxzID0gYygiYykiLCAiIiwgImQpIiwgIiIpKSwKbGVmdCA9IHRleHRfZ3JvYigiVHJvcGhpYyBOaWNoZSIsIHJvdCA9IDkwKSkKCnNwZWNpZXNfcGxvdDIKYGBgCmMpIFRoZSByZWR1bmRhbmN5L2Z1bGxuZXNzIG9mIHRoZSBuaWNoZXMgdGhhdCBhcmUgcHJlc2VudCBpbiBjaXRpZXMgd2l0aCAxMCUgb2YgdGhlIG1vc3QgdXJiYW5pc2VkIHNwZWNpZXMsIGFuZCB0aGUgcmVkdW5kYW5jeS9mdWxsbmVzcyBvZiB0aGUgbmljaGVzIHRoYXQgYXJlIHByZXNlbnQgaW4gY2l0aWVzIHdpdGggMjAlIG9mIHRoZSBtb3N0IHVyYmFuaXNlZCBzcGVjaWVzLgpkKSBUaGUgcGVyY2VudGFnZSBpbmNyZWFzZSBpbiByZWR1bmRhbmN5L2Z1bGxuZXNzIG9mIG5pY2hlcyBiZXR3ZWVuIHRoZSB0b3AgMTAlIG9mIG1vc3QgdXJiYW5pc2VkIHNwZWNpZXMgYW5kIHRoZSB0b3AgMjAlIG9mIG1vc3QgdXJiYW5pc2VkIHNwZWNpZXMsIGdyb3VwZWQgdXNpbmcgVHVrZXkgYmFzZWQgb24gYW4gYW5vdmEgb2YgdGhlIHBlcmNlbnRhZ2UgaW5jcmVhc2UgZ2l2ZW4gdGhlIHRyb3BpYyBuaWNoZS4gVGhpcyBzaG93cyB0aGUgYW1vdW50IG9mIHJlZHVuZGFuY3kgdGhhdCBpcyBpbmNyZWFzZWQgZnJvbSB0aGUgYm90dG9tIDI1JSBwZXJmb3JtaW5nIGhvdHNwb3RzIChob3RzcG90cyB3aXRoIDEwJSBvZiByZWdpb25hbCBwb29sKSBhbmQgdGhlIGJvdHRvbSA3NSUgb2YgcGVyZm9ybWluZyBob3RzcG90cyAoaG90c3BvdHMgd2l0aCAyMCUgb2YgcmVnaW9uYWwgcG9vbCkuCgoKYGBge3J9CmpwZWcoInNwZWNpZXNfcGxvdDEuanBnIiwgd2lkdGggPSA4MDAsIGhlaWdodCA9IDYwMCkKc3BlY2llc19wbG90MQpkZXYub2ZmKCkKCmpwZWcoInNwZWNpZXNfcGxvdDIuanBnIiwgd2lkdGggPSA4MDAsIGhlaWdodCA9IDYwMCkKc3BlY2llc19wbG90MgpkZXYub2ZmKCkKYGBgCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tClRyb3BoaWMgTmljaGUgQWNjdW11bGF0aW9uCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmBgYHtyfQphY2N1bXVsYXRpb24gPC0gcmVhZF9jc3YoJ3Ryb3BoaWNfbmljaGVfYWNjdW11bGF0aW9uLmNzdicpCmFjY3VtdWxhdGlvbgpgYGAKYGBge3J9Cm1lcmxpbl9hY2N1bXVsYXRpb24gPSBnZ3Bsb3QoYWNjdW11bGF0aW9uLCBhZXMoeCA9IHBlcmNlbnQsIHkgPSBtZXJsaW5fbmljaGVfY291bnQpKSArIAogIGdlb21fbGluZShsaW5ldHlwZSA9ICJkb3R0ZWQiKSArIAogIGdlb21fbGluZShhZXMobGluZXR5cGUgPSBtZXJsaW5fcmVtYWluaW5nX3NwZWNpZXMpLCBuYS52YWx1ZSA9ICJkYXNoIikgKwogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXM9YygiYmxhbmsiLCAic29saWQiKSwgZ3VpZGUgPSAibm9uZSIpICsKICBnZW9tX2hsaW5lKGRhdGEgPSAuICU+JSBncm91cF9ieSh0cm9waGljX25pY2hlKSAlPiUgZmlsdGVyKG1lcmxpbl9uaWNoZV9jb3VudCA9PSBtYXgobWVybGluX25pY2hlX2NvdW50KSksIGFlcyh5aW50ZXJjZXB0ID0gbWVybGluX25pY2hlX2NvdW50KSwgY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAwLjI1LCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDYpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBzaXplID0gNiksICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gNikpICsKICBmYWNldF93cmFwICh+IHRyb3BoaWNfbmljaGUpICsKICB4bGFiKCJQZXJjZW50YWdlIG9mIGFsbCBTcGVjaWVzIikgKyAKICB5bGFiKCJOdW1iZXIgb2YgTmljaGVzIikgKwogIGxhYnModGl0bGUgPSAiTWVybGluIE5pY2hlIEFjY3VtdWxhdGlvbiIpCgptZXJsaW5fYWNjdW11bGF0aW9uCmBgYAoKCmBgYHtyfQpiaXJkbGlmZV9hY2N1bXVsYXRpb24gPSBnZ3Bsb3QoYWNjdW11bGF0aW9uLCBhZXMoeCA9IHBlcmNlbnQsIHkgPSBiaXJkbGlmZV9uaWNoZV9jb3VudCkpICsgCiAgZ2VvbV9saW5lKGxpbmV0eXBlID0gImRvdHRlZCIpICsgCiAgZ2VvbV9saW5lKGFlcyhsaW5ldHlwZSA9IGJpcmRsaWZlX3JlbWFpbmluZ19zcGVjaWVzKSwgbmEudmFsdWUgPSAiZGFzaCIpICsKICBzY2FsZV9saW5ldHlwZV9tYW51YWwodmFsdWVzPWMoImJsYW5rIiwgInNvbGlkIiksIGd1aWRlID0gIm5vbmUiKSArCiAgZ2VvbV9obGluZShkYXRhID0gLiAlPiUgZ3JvdXBfYnkodHJvcGhpY19uaWNoZSkgJT4lIGZpbHRlcihiaXJkbGlmZV9uaWNoZV9jb3VudCA9PSBtYXgoYmlyZGxpZmVfbmljaGVfY291bnQpKSwgYWVzKHlpbnRlcmNlcHQgPSBiaXJkbGlmZV9uaWNoZV9jb3VudCksIGNvbG9yID0gImJsdWUiLCBzaXplID0gMC4yNSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2KSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgc2l6ZSA9IDYpLCAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDYpKSArCiAgZmFjZXRfd3JhcCAofiB0cm9waGljX25pY2hlKSArCiAgeGxhYigiUGVyY2VudGFnZSBvZiBhbGwgU3BlY2llcyIpICsgCiAgeWxhYigiTnVtYmVyIG9mIE5pY2hlcyIpICsKICBsYWJzKHRpdGxlID0gIkJpcmRsaWZlIE5pY2hlIEFjY3VtdWxhdGlvbiIpCgpiaXJkbGlmZV9hY2N1bXVsYXRpb24KYGBgCmBgYHtyfQphbm5vdGF0ZV9maWd1cmUoCiAgZ2dhcnJhbmdlKG1lcmxpbl9hY2N1bXVsYXRpb24gKyBycmVtb3ZlKCJ4bGFiIikgKyBycmVtb3ZlKCJ5bGFiIiksIAogICAgICAgICAgICBiaXJkbGlmZV9hY2N1bXVsYXRpb24gKyBycmVtb3ZlKCJ4bGFiIikgKyBycmVtb3ZlKCJ5bGFiIiksCiAgICAgICAgICAgIG5jb2wgPSAyLCBsYWJlbC54ID0gMCksCmxlZnQgPSB0ZXh0X2dyb2IoIk51bWJlciBvZiBOaWNoZXMgUHJlc2VudCIsIHJvdCA9IDkwKSwKYm90dG9tID0gdGV4dF9ncm9iKCJQZXJjZW50YWdlIG9mIGFsbCBTcGVjaWVzIC0gcmFua2VkIGJ5IHVyYmFuaXNhdGlvbiIpKQoKCmdnc2F2ZSgidHJvcGhpY19uaWNoZV9hY2N1bWxhdGlvbi5qcGciKQpgYGAKCgoK